C++ : Deep Copying of an Object

  • C/C++
  • Thread starter Hepth
  • Start date
  • Tags
    C++
In summary: There is need to declare a copy constructor, assignment operator, destructor for class Connection. In fact, you don't want to. The implicitly-defined functions do exactly what the doctor ordered. If you're of the pedantic sort, you can inform the reader of your code that you are explicitly using those implicitly declared and defined member functions:class Connection {public: // Default constructor Connection(double v=0.0) : val(v) {} // Copy constructor, assignment operator, and destructor Connection(const Connection&) = default; Connection& operator=(const Connection&) = default; ~Connection() = default;
  • #1
Hepth
Gold Member
464
40
I'm making a basic neural network, and I haven't programmed in an object oriented way since java in undergraduate. Everything lately has been c and fortran 77.

I have an object that is a "Network"
In addition to functions and locals, it includes a pointer to an array of another object "Layer"
Each Layer includes a pointer to an array of "Neuron"
Each Neuron includes a pointer to an array of "Connection"
Connection just has a double "val".

How do I create an operator and copy constructor such that when I have

Code:
Network A;
A.Randomize(); //Sets everything to random values at the Connection level
Network B = A; //Here I want to define a copy
B.Randomize(); //Randomize B

And then
A.Layers[0].Neurons[0].Connections[0].val
B.Layers[0].Neurons[0].Connections[0].val

should be different. As it stands, the basic shallow copy makes copies of the pointer locations, rather than the deep values contained. So A.Layer and B.Layer point to the same location, so any changes to B makes changes to A. I want to make a NEW duplicate, that does a deep copy.

Do I need to go to each class and add a more deep copy constructor with rules for EVERY pointer/array/object in that class, and how to copy itself deeply?

It feels like a lot of work, where if inside say Neuron class I have a bunch of different pointers, I would have to make the copy constructor copy the value of each one?

Sorry if its not clear, I have an idea of what I'm doing but I'm having trouble getting it done. It also doesn't help that I am working off of someone elses template to a very basic degree.
 
Technology news on Phys.org
  • #3
Hepth said:
Do I need to go to each class and add a more deep copy constructor with rules for EVERY pointer/array/object in that class, and how to copy itself deeply?

Pretty much so, yes. In fact, each class should have a destructor, a (deep) copy constructor, and an assignment operator (the "Rule of Three").

This would be easier if the classes used vectors instead of arrays. You can copy a vector of objects (e.g in an assignment statement), and it automatically copies all the objects it contains, according to their constructors. With arrays, you have to copy each object yourself. ?:)
 
  • Like
Likes D H
  • #4
jtbell said:
This would be easier if the classes used vectors instead of arrays.
What jtbell said!

Hepth said:
I have an object that is a "Network"
In addition to functions and locals, it includes a pointer to an array of another object "Layer"
Each Layer includes a pointer to an array of "Neuron"
Each Neuron includes a pointer to an array of "Connection"
Connection just has a double "val".
If you follow jtbell's advice, you don't need to write a copy constructor, assignment operator, or destructor. The C++ standard library contains some very powerful capabilities, they optimize very nicely, and they oftentimes eliminate the need to write those rule of three (C++11: rule of five) special member functions.

Code:
class Connection {
public:
   // Default constructor
   Connection(double v=0.0) : val(v) {}

   // Other member functions
...

   double val;
};

There is need to declare a copy constructor, assignment operator, destructor for class Connection. In fact, you don't want to. The implicitly-defined functions do exactly what the doctor ordered. If you're of the pedantic sort, you can inform the reader of your code that you are explicitly using those implicitly declared and defined member functions:

Code:
class Connection {
public:
   // Default constructor
   Connection(double v=0.0) : val(v) {}

  // Copy constructor, assignment operator, and destructor
  Connection(const Connection&) = default;
  Connection& operator=(const Connection&) = default;
  ~Connection() = default;

   // And in the case of C++11/14 ...
  Connection(Connection&&) = default;
  Connection& operator=(Connection&&) = default;
   // Other member functions
...

   double val;
};

I kind of like that myself. It's not too that extra typing, and it tells me as a reader of the code that the author of the class has explicitly thought about whether it makes sense to get those freebies.

What about higher levels? Here's neuron, which now uses a vector rather than a primitive array:

Code:
class Neuron {
public:
   // Default constructor, needed if you define a non-default constructor
   // and if you want a default constructor. I'm assuming C++11 here.
   Neuron() = default;

   // Defaulted special member functions.
   // Once again I'm being pedantic here. Now this is perhaps too much typing.
  Neuron(const Neuron&) = default;
  Neuron(Neuron&&) = default;
  Neuron& operator=(const Neuron&) = default;
  Neuron& operator=(Neuron&&) = default;
  ~Neuron() = default;
   ...
   std::vector<Connection> connections;
};

And similarly for classes Layer and Network.

The rule of three is a pain in the rear. The rule of five, and even bigger pain. The easiest way around this is to use Peter Sommerlad's "rule of zero": Write your classes so you don't need to define any of the special member functions that are subject to the rule of three / rule of five. Use standard library containers or smart points.
 
  • #5
DH, I'm going to implement it that way, but basically it becomes that YOUR copy is a shallow copy, but since I am using vectors rather than pointers to arrays, its easy and I can just use the normal shallow copy for everything. Right?

It doesn't solve the problem of if I had a pointer for some reason deep in my tree that the copy used would just copy the address rather than the value?
 
  • #6
Hepth said:
DH, I'm going to implement it that way, but basically it becomes that YOUR copy is a shallow copy, but since I am using vectors rather than pointers to arrays, its easy and I can just use the normal shallow copy for everything. Right?
It's a deep copy rather than a shallow copy if you replace all those primitive arrays with std::vectors.

Make a Neuron contain a vector of Connection objects, a Layer contain a vector of Neuron objects, a Network contain a vector of Layer objects. The implicitly defined copy constructor for Network invokes the std::vector copy constructor to make a copy of the source Network object's connections vector. The std::vector copy constructor makes an element-by-element copy. That means the Lay objects will be copied element by element, which in turn means the Neuron elements within each Layer will be copied element by element, which in turn means the Connection objects within each Neuron will copied element by element. That's a deep copy, just what you want, and you get it for free by following the rule of zero.
 
  • #7
Ok, thanks a million! Time to rewrite all of this...
 
  • #8
It may also be useful to add functions that serialize the class data - including those that have sub-structures and sub-classes within the class you are trying to serialize.

Depending on how clever you want to get you can set up macro's and do a lot of fancy stuff that sets up some structures in the class that allow procedures to serialize every thing without you having to write the individual code yourself. You could also just register variables with some global table as well.

If you ever want to save and restore your data easily then I would recommend checking out how to serialize your class data.
 

1. What is the difference between shallow copying and deep copying of an object in C++?

Shallow copying involves creating a new object that points to the same memory location as the original object. This means that any changes made to one object will also affect the other. In contrast, deep copying involves creating a new object and copying the values of all the member variables from the original object to the new object. This results in two separate objects with independent values.

2. How is deep copying implemented in C++?

In C++, deep copying can be implemented by creating a copy constructor or overloading the assignment operator. The copy constructor is invoked when a new object is created from an existing object, and the assignment operator is used when assigning a value to an already existing object.

3. Why is deep copying important in C++?

Deep copying is important in C++ because it ensures that objects are truly independent and changes made to one object do not affect the other. This is especially useful when working with complex objects that contain dynamically allocated memory, as shallow copying can cause memory leaks and other unexpected behavior.

4. Can deep copying be done for all types of objects in C++?

Yes, deep copying can be done for all types of objects in C++. However, it is important to note that the default copy constructor and assignment operator provided by the compiler may not perform deep copying for objects with dynamically allocated memory. Therefore, it is necessary to define custom copy constructors and assignment operators for classes that contain pointers or other dynamically allocated memory.

5. Are there any alternatives to deep copying in C++?

Yes, there are a few alternatives to deep copying in C++. One option is to use smart pointers, such as std::shared_ptr or std::unique_ptr, which handle memory management automatically and can prevent issues with shallow copying. Another alternative is to use a copy-on-write (COW) technique, where the original object is only copied when a modification is made, otherwise, the copy simply points to the same memory location as the original.

Similar threads

  • Programming and Computer Science
2
Replies
40
Views
2K
  • Programming and Computer Science
Replies
25
Views
2K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
2
Replies
35
Views
2K
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
23
Views
2K
  • Programming and Computer Science
Replies
31
Views
2K
  • Programming and Computer Science
Replies
1
Views
999
  • Programming and Computer Science
Replies
2
Views
1K
Back
Top