Reputation: 215
Why
struct X{};
X x;
X *q = &x;
std::shared_ptr<X> p(&x);
causes error and
X x;
X *q = &x;
std::shared_ptr<X> p0 = std::make_shared<X>(x);
doesn't cause runtime error?
I read that in the first case I have "two different pointers, pointing to the same data and one of them is shared"
But I think that there is the same situation in the second case?
free(): invalid pointer
Upvotes: 3
Views: 342
Reputation: 38315
In the first case, the object x
is deleted although it's lifetime already ends with the end of its scope. Here, you create an instance on the stack and in your scope :
X x; // lifetime automatically ends at the end of the scope
Then, you ask the std::shared_ptr
to control the lifetime of the address of x
, too.
std::shared_ptr<X> p(&x); // calls delete at the end of the scope
Hence, you free the same variable twice, which is undefined behavior. In the second case, you create a std::shared_ptr
to a copied instance that is independent of the x
instance.
std::shared_ptr<X> p0 = std::make_shared<X>(x); // Copies x, then deletes the copy
This is no problem, as both objects are only deleted once.
Note the semantics of std::make_shared
here: the arguments you pass to it are forwarded to the constructor of its template argument. Hence you trigger the compiler-generated copy constructor X(const X&)
to be invoked. This is very different from creating a std::shared_ptr
from an already existing pointer to via std::shared_ptr p(&x);
.
Upvotes: 9
Reputation: 182865
In the first case, p
takes ownership of x
. When p
goes out of scope, it deletes x
. But x
was not dynamically allocated. Oops.
You don't have that situation in the second case. The make_shared
function dynamically allocates a new, shared object. When p0
goes out of scope, it destroys that newly-created object. Note that, in this case, *p0
is not x
but the new object.
Upvotes: 7