Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does enable_shared_from_this and make_shared provide the same optimization

As I understand make_shared<T>(...) may provide some memory allocation optimization (it may allocate reference counter within same memory block as instance of class T).

Do enable_shared_from_this provides the same optimization? So:

class T : std::enable_shared_from_this<T> {};
...
auto t = std::shared_ptr<T>(new T);

Is the same as:

class T {};
...
auto t = std::make_shared<T>();

If not take in account sizeof(T).

like image 966
Dmitry Poroh Avatar asked Jul 15 '16 13:07

Dmitry Poroh


1 Answers

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.

like image 52
Jonathan Wakely Avatar answered Sep 20 '22 22:09

Jonathan Wakely