There are several questions that cover the behavior of std::enable_shared_from_this
, but I don't think that this is a duplicate.
Classes that inherit from std::enable_shared_from_this
carry a std::weak_ptr
member. When the application creates a std::shared_ptr
pointing to a subclass of std::enable_shared_from_this
, the std::shared_ptr
constructor checks the std::weak_ptr
, and if it is not initialized, initializes it and uses the std::weak_ptr
control block for the std::shared_ptr
. However, if the std::weak_ptr
is already initialized, the constructor just creates a new std::shared_ptr
with a new control block. This sets the application up to crash when the reference count of one of the two std::shared_ptr
instances goes to zero and deletes the underlying object.
struct C : std::enable_shared_from_this<C> {};
C *p = new C();
std::shared_ptr<C> p1(p);
// Okay, p1 and p2 both have ref count = 2
std::shared_ptr<C> p2 = p->shared_from_this();
// Bad: p3 has ref count 1, and C will be deleted twice
std::shared_ptr<C> p3(p);
My question is: why does the library behave this way? If the std::shared_ptr
constructor knows that the object is a std::enable_shared_from_this
subclass and bothers to check the std::weak_ptr
field, why doesn't it always use same control block for the new std::shared_ptr
, thus avoiding a potential crash?
And for that matter, why does the method shared_from_this
fail when the std::weak_ptr
member is not initialized, instead of just initializing it and returning a std::shared_ptr
?
It seems strange that the library works the way that it does, since it fails in situations when it could easily succeed. I'm wondering if there were design considerations/limitations that I don't understand.
I am using Clang 8.0.0 in C++17 mode.