Weak pointer to this in constructor

2019-04-06 15:40发布

问题:

I understand it is not possible to obtain a shared_ptr by calling shared_from_this() from the constructor of a class, as the object is not yet constructed. Is it possible however to obtain a weak_ptr to the object from the constructor? Some boost forum posts discussing a "weak_from_raw()" method suggests that it may be possible.

Edit: Boost form discussing weak_from_raw http://lists.boost.org/boost-users/2010/08/61541.php

回答1:

I think what you're referencing is this. Which seems not to have been merged to the boost release (may be wrong about that).

From the boost docs:

Frequently Asked Questions

Q. Can an object create a weak_ptr to itself in its constructor?

A. No. A weak_ptr can only be created from a shared_ptr, and at object construction time no shared_ptr to the object exists yet. Even if you could create a temporary shared_ptr to this, it would go out of scope at the end of the constructor, and all weak_ptr instances would instantly expire.

The solution is to make the constructor private, and supply a factory function that returns a shared_ptr:

class X
{
private:

    X();

public:

    static shared_ptr<X> create()
    {
        shared_ptr<X> px(new X);
        // create weak pointers from px here
        return px;
    }
};


回答2:

See: http://boost.org/doc/libs/1_42_0/libs/smart_ptr/sp_techniques.html#in_constructor

The issue isn't that the object isn't constructed. The issue is that the shared_ptr hasn't been constructed. If all you were to do was to create a shared_ptr and send it off somewhere everything would be fine. It's when you try to create a shared_ptr to contain the object you just created. There's no way to connect the two and thus you have a big problem.

The way that shared_from_this works is that it expects you to put the object is a shared_ptr before ever calling shared_from_this to gain access to it. Since you haven't yet done so, since the object's constructor hasn't finished and thus the shared_ptr is not connected to it, you can't call shared_from_this.

You'd have exactly the same issue with the weak_ptr.

So, in other words, this absurd construct would work:

struct absurd
{
  absurd()
  {
    register(shared_ptr<absurd>(this));
  }
};

...
new absurd; // better not assign to a shared_ptr!!!

But you really don't want to do this.