36

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.

pmr
  • 58,701
  • 10
  • 113
  • 156
Marc
  • 767
  • 1
  • 10
  • 23
  • It seems that `e` also deletes `o`? How so? You can add a destructor with a print statement to see what is happening. – pmr Apr 01 '14 at 09:59
  • You can put log in your Event destructor. for example std::cout. – cbel Apr 01 '14 at 10:01

2 Answers2

29

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.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
10

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.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 2
    I am having the problem you're describing. How would I create a copy of the shared_ptr to Base class from another shared_ptr to Base class, while retaining the fact that it is actually a Derived class? – Iron Attorney Jul 26 '17 at 08:59
  • 1
    My best solution so far is: 'code' std::shared_ptr newBase; Derived copiedJob = *static_cast(obj.mp_base.get()); newBase = std::make_shared(copiedJob); '\code' – Iron Attorney Jul 26 '17 at 09:05
  • 2
    @IronAttorney use `\`` for inline code markup, not 'code'. See https://stackoverflow.com/editing-help#comment-formatting – Jonathan Wakely Aug 09 '17 at 16:31