Is this trick, to make calling shared_from_this() in the constructor 'just work', dangerous?

痞子三分冷 提交于 2019-12-10 13:33:00

问题


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.


回答1:


That's not dangerous.

The documented restriction is: cppreference

Before calling shared_from_this, there should be at least one std::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



来源:https://stackoverflow.com/questions/33069674/is-this-trick-to-make-calling-shared-from-this-in-the-constructor-just-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!