views:

111

answers:

2

I have an object which has both a copy constructor and assignment operator defined. It is enclosed inside a shared pointer.

I want to make another shared pointer that contains a copy of the original shared pointer (i.e. new shared pointer to a new memory location, which however, has the same data as the original object).

Thanks for any assistance.

+11  A: 

You invoke the copy constructor when creating the new object:

std::shared_ptr<C> ptr1(new C());      // invokes the default constructor
std::shared_ptr<C> ptr2(new C(*ptr1)); // invokes the copy constructor

In this case, it's really no different than if you have regular, dumb pointers.

James McNellis
I find the question slightly hard to read, but is that what the OP is asking? Or are they asking how to create another shared pointer to the object?
Martin York
@Martin: I _think_ so, but I'm not sure now. The "pointer to a new memory location" was what led me to this being the answer, but I could be wrong.
James McNellis
James you read my question correctly the first time, and the answer was exactly what I was looking for.Reading back, I am amazed how you made any sense of my question. Many hours of debugging had left my brain quite scrambled...Thanks for the answe again.
+1  A: 

Often I'll be using shared pointers with polymoprphic types. In this case you can't use the method suggested by James McNellis.

class Base
{
 ...
  virtual void doSomething()=0;
};

class Derived : public Base
{
  ...
  void doSomething() { ... }
};

std::shared_ptr<Base> ptr(new Derived);
std::shared_ptr<Base> cpy( new Base( *ptr ) ); // THIS DOES NOT COMPILE!

So what I do instead is to add a clone function into the base class, and implement it in the derived classes.

class Base
{
 ...
  virtual void doSomething()=0;
  virtual std::shared_ptr<Base> clone() const =0;
};

class Derived : public Base
{
  ...
  void doSomething() { ... }
  std::shared_ptr<Base> clone() const 
  { 
     return std::shared_ptr<Base>( new Derived( *this ) );
  }
};


std::shared_ptr<Base> ptr(new Derived);
std::shared_ptr<Base> cpy = ptr->clone();
Michael Anderson
Actually the the top case does compile if you have no pure virtual functions. you just wont get a proper copy of the object, it'll get sliced to the base class...
Michael Anderson
And you probably want your clone method to return a Base*, so derived classes can take advantage of covarient return types
Terry Mahaffey
... plus having `shared_ptr` in your class interface adds unneeded coupling. You are forcing (`shared_ptr` cannot relinquish ownership) your users into using an specific type of smart pointer regardless or their use of the data. They might prefer using `scoped_ptr`, or `unique_ptr`, or a pointer container that handles ownership. Maybe even their own (locking?) smart pointer... The decision of smart pointer should be in the receiving call, where the most information is known.
David Rodríguez - dribeas
C++ gets very ham-fisted with this sort of thing. Writing a one-liner clone function for every descendant class? _Laaaaame._
Andres Jaan Tack
@David Its a trade off, but returning a shared pointer allows me to control the destruction of the object, rather than the caller. Otherwise using a caching, or my own allocators can lead to trouble. Now there are ways around some of those issues, but they'd obscure the core of the idea.
Michael Anderson
@Terry unfortunately you can't return smart pointers in a covariant manner. But if you want to use raw pointers in the return then using covariant return is certainly better.
Michael Anderson
If you really feel that you need to keep care of the memory for your users, return an `std::auto_ptr` or an `unique_ptr` where the user can actually release the object from that smart pointer and pass it into whatever choice of smart pointer they want to use. By returning `shared_ptr` you are forcing your decision on users.
David Rodríguez - dribeas
@Michael I know, that was exactly my point. That's why I suggested changing the return type to Base*
Terry Mahaffey