0

For the below code, when v is copied, the members of Model class do not get copied.

#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
using namespace std;

    class SomeNewClass
    {
    public:
       int a;
    };

    class Model
    {
    public:
       int i;
       SomeNewClass* s;//A deep copy won't happen here automatically

       Model() {}
       Model(const Model& m):i(m.i)
       {
        cout<<"Model Copy ctor invoked"<<endl;
       }
    };

    class ModelInherit : public Model
    {
    public:
       int j;

       ModelInherit() {}
       ModelInherit(const ModelInherit& m):j(m.j)
       {
          //i=m.i;//I don't want to copy like this. I want the copy ctor of Model to be invoked
          cout<<"ModelInherit Copy ctor invoked"<<endl;
       }
    };

    int main()
    {
       boost::ptr_vector<ModelInherit> v;
       v.push_back(new ModelInherit);
       v[0].j = 10;
       v[0].i = 20;
       v[0].s = new SomeNewClass();
       v[0].s->a = 99;

       boost::ptr_vector<ModelInherit> v2( v );
       cout<< v2[0].j <<endl;
       cout<< v2[0].i <<endl;
       //cout<< v2[0].s->a <<endl;//segmentation fault
    }

What is important to note is that if you comment out the copy constructor of ModelInherit, then the pointer container automatically copies the i variable in the Model class. Sad part is that "SomeNewClass* s" does not get copied. No deep copy.

So my questions are:

  • Do you know how to invoke the copy constructor of the Model class in the above code?
  • How do I ensure a deep copy when the pointer container is automatically copying variables so that even the 'a' variable of SomeNewClass gets copied?
Nav
  • 19,885
  • 27
  • 92
  • 135

2 Answers2

2

(1) To invoke Model copy constructor, change your ModelInherit copy constructor like following:

ModelInherit(const ModelInherit& m): Model(m), j(m.j) {}

(2) Deep copy can be done like this:

Model(const Model& m): i(m.i), s(0)
{
  if(m.s != 0)
    this->s = new SomeNewClass(*(m.s));
  cout<<"Model Copy ctor invoked"<<endl;
}

And declare a copy constructor for SomeNewClass like below:

SomeNewClass(const SomeNewClass &copy) : a(copy.a)
{
  cout<<"SomeNewClass Copy ctor invoked"<<endl;
}

Don't forget to free Model::s in destructor, otherwise it will leak memory:

~Model () { delete this->s; }  // it's ok if s = 0
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • the default copy-constructor generated by the compiler for `SomeNewClass` is enough.. – Nawaz Apr 09 '11 at 12:12
  • Yes, but in case if he has some more pointer inside it which has to be deep copied, then he can keep editing into it. I assume that, `SomeNewClass` is not limited to what he has mentioned. – iammilind Apr 09 '11 at 12:14
  • Erm...actually the doubt was that when the copy ctor of ModelInherit is commented out, the container automatically does a copy. But it does not do a deep copy. Maybe the solution lies in the clone function: http://www.boost.org/doc/libs/1_46_1/libs/ptr_container/doc/examples.html#objects-are-cloned-before-insertion-inserted-pointers-are-owned-by-the-container – Nav Apr 11 '11 at 04:35
  • @Nav, in built copy constructor or assignment operator always do "Shallow copy". They don't differentiate between normal data type and pointer variables. "Deep copy" comes into picture only when you deal with pointers. For deep copy, you can either use such library or define own custom copy constructor. – iammilind Apr 11 '11 at 04:58
1

Invoking base class copy-constructor is easy:

ModelInherit(const ModelInherit& m): Model(m), j(m.j) {}
                                  //^^^^^^^^ note this

Model(m) invokes base class copy-constructor; the parameter m implicitly converts into base class.

In the base class copy-constructor, you've to manually deep-copy m.s.

Nawaz
  • 353,942
  • 115
  • 666
  • 851