C++ : Deep Copying of an Object

  • C/++/#
  • Thread starter Hepth
  • Start date
  • #1
Hepth
Gold Member
448
39

Main Question or Discussion Point

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 im working off of someone elses template to a very basic degree.
 

Answers and Replies

  • #3
jtbell
Mentor
15,518
3,353
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
Reactions: D H
  • #4
D H
Staff Emeritus
Science Advisor
Insights Author
15,393
683
This would be easier if the classes used vectors instead of arrays.
What jtbell 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
Hepth
Gold Member
448
39
DH, I'm going to implement it that way, but basically it becomes that YOUR copy is a shallow copy, but since im 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
D H
Staff Emeritus
Science Advisor
Insights Author
15,393
683
DH, I'm going to implement it that way, but basically it becomes that YOUR copy is a shallow copy, but since im 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
Hepth
Gold Member
448
39
Ok, thanks a million! Time to rewrite all of this...
 
  • #8
chiro
Science Advisor
4,790
131
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.
 

Related Threads on C++ : Deep Copying of an Object

  • Last Post
Replies
4
Views
26K
  • Last Post
Replies
10
Views
769
Replies
1
Views
1K
  • Last Post
3
Replies
52
Views
2K
Replies
1
Views
4K
  • Last Post
Replies
1
Views
2K
  • Last Post
Replies
1
Views
869
Replies
45
Views
5K
Replies
1
Views
496
Top