|
|
Protected member functions | ||||
Public member functions | ||||
Defined in header <memory> | ||
template<class T> class enable_shared_from_this; | (since C++11) | |
std::enable_shared_from_this
allows an objectt that is currently managed by astd::shared_ptr namedpt to safely generate additionalstd::shared_ptr instancespt1,pt2 etc. that all share ownership oft withpt.
Publicly inheriting fromstd::enable_shared_from_this<T>
provides the typeT
with a member functionshared_from_this
. If an objectt of typeT
is managed by astd::shared_ptr<T> namedpt, then callingT::shared_from_this
will return a newstd::shared_ptr<T> that shares ownership oft withpt.
Contents |
Member | Description |
mutablestd::weak_ptr<T>weak_this | the object tracking the control block of the first shared owner of*this (exposition-only member object*) |
constructs anenable_shared_from_this object(protected member function) | |
destroys anenable_shared_from_this object(protected member function) | |
returns a reference to*this (protected member function) | |
returns astd::shared_ptr which shares ownership of*this (public member function) | |
(C++17) | returns astd::weak_ptr which shares ownership of*this (public member function) |
The constructors ofstd::shared_ptr detect the presence of an unambiguous and accessible (i.e. public inheritance is mandatory)enable_shared_from_this
base and assign the newly createdstd::shared_ptr toweak_this
if not already owned by a livestd::shared_ptr. Constructing astd::shared_ptr for an object that is already managed by anotherstd::shared_ptr will not consultweak_this
and thus will lead to undefined behavior.
It is permitted to callshared_from_this
only on a previously shared object, i.e. on an object managed bystd::shared_ptr<T>. Otherwise,std::bad_weak_ptr is thrown (by thestd::shared_ptr constructor from a default-constructedweak_this
).
enable_shared_from_this
provides the safe alternative to an expression likestd::shared_ptr<T>(this), which is likely to result inthis being destructed more than once by multiple owners that are unaware of each other (see example below).
#include <iostream>#include <memory> class Good:public std::enable_shared_from_this<Good>{public:std::shared_ptr<Good> getptr(){return shared_from_this();}}; class Best:public std::enable_shared_from_this<Best>{struct Private{explicit Private()=default;}; public:// Constructor is only usable by this class Best(Private){} // Everyone else has to use this factory function// Hence all Best objects will be contained in shared_ptrstaticstd::shared_ptr<Best> create(){returnstd::make_shared<Best>(Private());} std::shared_ptr<Best> getptr(){return shared_from_this();}}; struct Bad{std::shared_ptr<Bad> getptr(){returnstd::shared_ptr<Bad>(this);} ~Bad(){std::cout<<"Bad::~Bad() called\n";}}; void testGood(){// Good: the two shared_ptr's share the same objectstd::shared_ptr<Good> good0=std::make_shared<Good>();std::shared_ptr<Good> good1= good0->getptr();std::cout<<"good1.use_count() = "<< good1.use_count()<<'\n';} void misuseGood(){// Bad: shared_from_this is called without having std::shared_ptr owning the callertry{ Good not_so_good;std::shared_ptr<Good> gp1= not_so_good.getptr();}catch(std::bad_weak_ptr& e){// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)std::cout<< e.what()<<'\n';}} void testBest(){// Best: Same but cannot stack-allocate it:std::shared_ptr<Best> best0= Best::create();std::shared_ptr<Best> best1= best0->getptr();std::cout<<"best1.use_count() = "<< best1.use_count()<<'\n'; // Best stackBest; // <- Will not compile because Best::Best() is private.} void testBad(){// Bad, each shared_ptr thinks it is the only owner of the objectstd::shared_ptr<Bad> bad0=std::make_shared<Bad>();std::shared_ptr<Bad> bad1= bad0->getptr();std::cout<<"bad1.use_count() = "<< bad1.use_count()<<'\n';}// UB: double-delete of Bad int main(){ testGood(); misuseGood(); testBest(); testBad();}
Possible output:
good1.use_count() = 2bad_weak_ptrbest1.use_count() = 2bad1.use_count() = 1Bad::~Bad() calledBad::~Bad() called*** glibc detected *** ./test: double free or corruption
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2179 (P0033R1) | C++11 | given typeT derived fromenable_shared_from_this , the behavior ofconstructing twostd::shared_ptr<T>s from the sameT* object was unclear | the behavior is undefined in this case |
LWG 2529 (P0033R1) | C++11 | it was unclear how the underlyingstd::weak_ptr is updated | made clear |
(C++11) | smart pointer with shared object ownership semantics (class template)[edit] |
creates a shared pointer that manages a new object (function template)[edit] |