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
Before calling
shared_from_this
, there should be at least onestd::shared_ptr
p
that owns*this
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
or shared_pointer<T>(new T)
cannot complete before the T
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.
Using a friend factory function that returns the
shared_ptr<T>
could be one approach.
--> See also The Pit Of Success
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With