Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly duplicate an object given its shared_ptr

I'm trying to make a duplicate of an object of a custom class Event. I have a shared pointer to the object that I've obtained from its allocation:

std::shared_ptr<Event> e = std::make_shared<Event>(); 

In order to get a true duplicate of e (not just a copy of the pointer) I've tried:

std::shared_ptr<Event> o = std::make_shared<Event>(*e); 

But I'm not sure if this is the correct way as it seems that if I delete e it also deletes o...

Btw, I haven't defined a copy constructor Event::Event(const Event &orig) but in my understanding this is not necessary as the compiler provides a default copy constructor. The event class only contains variables and no further pointers.

like image 302
Marc Avatar asked Apr 01 '14 09:04

Marc


People also ask

Can you copy shared_ptr?

After you initialize a shared_ptr you can copy it, pass it by value in function arguments, and assign it to other shared_ptr instances.

What does shared_ptr get () do?

std::shared_ptr::getReturns the stored pointer. The stored pointer points to the object the shared_ptr object dereferences to, which is generally the same as its owned pointer.

Can you return a shared_ptr?

So the best way to return a shared_ptr is to simply return by value: shared_ptr<T> Foo() { return shared_ptr<T>(/* acquire something */); }; This is a dead-obvious RVO opportunity for modern C++ compilers.

Can shared_ptr be Nullptr?

A null shared_ptr does serve the same purpose as a raw null pointer. It might indicate the non-availability of data. However, for the most part, there is no reason for a null shared_ptr to possess a control block or a managed nullptr .


2 Answers

std::make_shared is just a simple template function that creates the objects, passing all arguments to the constructor :

template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args) {   return shared_ptr<T>( new T( std::forward<Args>( args )... ) ); } 

In your particular case :

std::shared_ptr<Event> o = std::make_shared<Event>(*e); 

the object is copied.

If your code is such :

void foo() {     // create new object using default constructor     std::shared_ptr<Event> e = std::make_shared<Event>();     // create new object using copy constructor constructor     std::shared_ptr<Event> o = std::make_shared<Event>(*e); } 

then of course both objects are destroyed, when they go out of scope.

like image 83
BЈовић Avatar answered Sep 28 '22 04:09

BЈовић


What you tried should work correctly, if the dynamic type of *e is Event, and not some class derived from Event. (If *e is actually an object derived from Event then you will create a new Event (not the derived type) as a copy of the base class part of *e i.e. you will "slice" *e).

Since you create e using make_shared<Event>() you know that in this case it really is an Event, so std::make_shared<Event>(*e) should make a new shared_ptr that owns a copy of *e.

like image 31
Jonathan Wakely Avatar answered Sep 28 '22 05:09

Jonathan Wakely