As mentioned by other users, calls to shared_from_this for instances not owned by shared_ptr will lead to undefined behavior (this is usually an exception, but there are no guarantees).
So why another answer?
Since I asked the same question myself and got almost the same answer, then I began to struggle with another question that arose immediately after that - how can I guarantee that all instances are managed using shared_ptr ?
For completeness, I will add another answer with a few details about this aspect.
Here's a simple solution that was not mentioned before.
So a simple solution, really: private constructors, factory method and variable templates.
It follows a snippet that mixes them all together in a minimal example:
#include<memory> #include<utility> class C: public std::enable_shared_from_this<C> { C() = default; C(const C &) = default; C(C &&) = default; C& operator=(const C &) = default; C& operator=(C &&c) = default; public: template<typename... Args> static std::shared_ptr<C> create(Args&&... args) noexcept { return std::shared_ptr<C>{new C{std::forward<Args>(args)...}}; } std::shared_ptr<C> ptr() noexcept { return shared_from_this(); } }; int main() { std::shared_ptr<C> c1 = C::create(); std::shared_ptr<C> c2 = C::create(*c1); std::shared_ptr<C> c3 = c2->ptr(); // these won't work anymore... // C c4{}; // std::shared_ptr<C> c5 = std::make_shared<C>(); // std::shared_ptr<C> c6{new C{}}; // C c7{*c1}; // ... and so on ... }
The main (trivial?) Idea is to prohibit the explicit construction of new instances, but using the factory method called create .
Variadic templates are used to avoid writing multiple factory methods, nothing more. Perfect shipment helps us make the right way.
Pretty simple, right? In any case, it took me a while to figure this out, so I hope this helps future readers develop the same doubts.
source share