Do enable_shared_from_this provides the same optimization? So:
No. As you can see from the wording in the standard, enable_shared_from_this<T>
has a weak_ptr<T>
data member. That adds a weak_ptr<T>
to the class, which has a pointer to the control block that contains the reference counts. It doesn't contain the reference counts directly. The control block containing the reference counts still exists external to the object.
The control block containing the reference counts must outlive the object, so that other weak_ptr
objects that used to refer to the object can still access the control block, to check whether it has expired.
If the control block was inside the object it would be destroyed when the object was destroyed, and it would not be possible for a dangling weak_ptr
to safely determine if the object had expired. In theory the memory of the control block could remain allocated and still be used and the reference counts updated, even though the object they were part of was destroyed, but that seems pretty ugly (and it would mean the object would not be destroyed with delete
, it would require an explicit destructor call and explicit operator delete
call to free the memory).
You also couldn't use the embedded control block if the owning shared_ptr
was created with a custom deleter or custom allocator, because the size of those objects would not be known in advance. In such cases you'd still need to allocate an external control block in addition to the one embeded in the enable_shared_from_this<T>
base class, wasting even more space.
enable_shared_from_this
is relevant when you already have a shared pointer. – Mazzardp = make_shared<T>()
orp = shared_ptr<T>(new T())
. Either way, you can then sayp->shared_from_this()
to get another share. – Mazzardenable_shared_from_this
allow to "retrieve" ashared_ptr
from an instance (owned byshared_ptr
). – Mountenable_shared_from_this
. Withmake_shared
you have a single allocation, and withshared_ptr<T>(new T)
you have two separate allocations. – Mazzard