Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C++ : Deep Copying of an Object

  1. Feb 4, 2015 #1

    Hepth

    User Avatar
    Gold Member

    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 (Text):

    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.
     
  2. jcsd
  3. Feb 4, 2015 #2

    jedishrfu

    Staff: Mentor

  4. Feb 4, 2015 #3

    jtbell

    User Avatar

    Staff: Mentor

    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. ?:)
     
  5. Feb 4, 2015 #4

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    What jtbell said!

    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 (Text):

    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 (Text):

    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 (Text):

    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.
     
  6. Feb 4, 2015 #5

    Hepth

    User Avatar
    Gold Member

    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?
     
  7. Feb 4, 2015 #6

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    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.
     
  8. Feb 4, 2015 #7

    Hepth

    User Avatar
    Gold Member

    Ok, thanks a million! Time to rewrite all of this...
     
  9. Feb 17, 2015 #8

    chiro

    User Avatar
    Science Advisor

    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.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: C++ : Deep Copying of an Object
Loading...