tags:

views:

731

answers:

3

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...

+2  A: 

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
I don't see the use of the function `copy` …
Konrad Rudolph
second line in the main function.
Mykola Golubyev
@Mykola: I see it – but I don't get it: it simply makes no sense. Sorry.
Konrad Rudolph
The code now do what the question is asked. It makes B to accept just pointers. So If you want you pass a copy if don't you pass a pointer. If you make B to copy pointer in constructor you limit functionality of B.
Mykola Golubyev
I've changed 'copy' to 'copyOf' to emphasize that it is a function.
Mykola Golubyev
A: 

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
Wait wait. If object has a raw pointers - be careful.
Mykola Golubyev
+1. I don't see any reason to downvote your answer. On the contrary.
Benoît
Mykola: what raw pointer? That's not possible here. This answer is completely correct.
Konrad Rudolph
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
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
True, as I said - it is just a warn to save Answerer time in the future.
Mykola Golubyev
+2  A: 

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.

Shmoopty
Or just a member of the class.
Nikolai N Fetissov