Question for the C++ experts.
We all know that calling shared_from_this() in the class constructor will result in a bad_weak_ptr exception, because no shared_ptr to the instance has been created yet.
As a work-around for that, I came up with this trick:
class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
MyClass() {}
MyClass( const MyClass& parent )
{
// Create a temporary shared pointer with a null-deleter
// to prevent the instance from being destroyed when it
// goes out of scope:
auto ptr = std::shared_ptr<MyClass>( this, [](MyClass*){} );
// We can now call shared_from_this() in the constructor:
parent->addChild( shared_from_this() );
}
virtual ~MyClass() {}
};
Someone argued that this is not safe, as the object has not yet been fully formed. Is he right about that?
I'm not using 'this' to access member variables or functions. Furthermore, all member variables have already been initialized, provided I used initializer lists. I don't see how this trick could be unsafe.
Edit: it turns out this trick indeed creates unwanted side-effects. The shared_from_this()
will point to the temporary shared_ptr
and if you're not careful, the parent-child relationship in my sample code will break. The implementation of enable_shared_from_this()
simply does not allow it. Thanks, Sehe, for pointing me in the right direction.
That's not dangerous.
The documented restriction is: cppreference
Nowhere does it say that it can't be used from inside the constructor /for this reason/.
It's just a-typical. That's because under normal circumstances, a
make_shared
orshared_pointer<T>(new T)
cannot complete before theT
constructor has exited.Caveat: the object isn't fully formed so you cannot legally invoke any virtual methods (at the penalty of Undefined Behaviour).
Guideline Since it's possible to use this class wrong (e.g. using
shared_ptr<T>(new T)
which creates a second shared_ptr with the same underlying pointer value... oops) you should prefer a design that prevents this.--> See also The Pit Of Success