2

I have some library code (I cannot not change the source code) that returns a pointer to an object (B). I would like to store this pointer as shared_ptr under a class with this type of constructor:

class A
{
  public:
   A(boost::shared_ptr<B> val);
   ...
  private:
   boost::shared_ptr<B> _val;
   ...
};

int main()
{
   B *b = SomeLib();
   A a(b); //??
   delete b;
   ...
} 

That is, I would like to make a deep-copy of b and control its life-time under a (even if original b is deleted (delete b), I still have an exact copy under a).

I'm new to this, sorry if it seems trivial...

Paul Morie
  • 15,528
  • 9
  • 52
  • 57
bob
  • 1,941
  • 6
  • 26
  • 36

3 Answers3

2

If the library defines this B object, the library should provide (or outright prohibit) the mechanism for copying B.

As a sidenote,

If your class A is exclusively controlling the lifetime of this copied object, the smart pointer you really want to use is boost::scoped_ptr.

boost::shared_ptr is named after its ability to share lifetime responsibility, which it sounds like you don't want. scoped_ptr won't let that accidentally happen.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
1

As you say, you have to copy them not just copy a pointer. So either B already has implemented 'clone' method or you have to implement some external B* copy(B* b) which will create new B with same state.

In case B has implemented copy constructor you can implement copy as just

B* copyOf(B* b)
{
    return new B(*b);
}

In case B has implemented clone method or similar you can implement copy as

B* copyOf(B* b)
{
    return b->clone();
}

and then your code will look like

int main()
{
   B *b = SomeLib();
   A a(copyOf(b));
   delete b;
   ...
}
Mykola Golubyev
  • 57,943
  • 15
  • 89
  • 102
1

Deep-copying is implemented trivially in C++ by the copy constructor since in C++, all objects have value semantics by default. Copying in such a way doesn't work for polymorphous objects though – in such cases, you'd have to implement a virtually overridden clone method in your class.

But in all other cases, simply writing

A(boost::shared_ptr<B> val) : _val(new B(*val)) { }

will do.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    +1. I don't see any reason to downvote your answer. On the contrary. – Benoît May 20 '09 at 13:13
  • Mykola: what raw pointer? That's not possible here. This answer is completely correct. – Konrad Rudolph May 20 '09 at 13:58
  • 1
    First of all - I didn't minus you and just warn. Here is the warning: If B creates some objects inside and store them to use and B hasn't implemented copy constructor, default copy constructor will just copy pointers to the objects and not the objects, thus in destructor each B will delete the same data. – Mykola Golubyev May 20 '09 at 14:07
  • 1
    Mykola: well, true – this is defined and expected behaviour in C++ and it's B's job to provide an appropriate copy constructor, if needed. However, this never invalidates my above code (which is idiomatic C++). It just means B might have a bug. – Konrad Rudolph May 20 '09 at 14:17
  • True, as I said - it is just a warn to save Answerer time in the future. – Mykola Golubyev May 20 '09 at 14:22
  • @Mykola Golubyev - do you give that warning every time you see a C++ sample that involves copying an object? That must keep you busy! – Daniel Earwicker Dec 02 '11 at 11:50