【问题标题】:Why doesn't aliasing constructor of std::shared_ptr initialize std::enabled_shared_from_this?为什么 std::shared_ptr 的别名构造函数不初始化 std::enabled_shared_from_this?
【发布时间】:2015-08-28 04:20:26
【问题描述】:

考虑以下代码:

struct Foo : std::enable_shared_from_this<Foo>
{

};

struct Bar
{
    Foo foo;
};

int main()
{
    std::shared_ptr<Bar> bar_p(new Bar);

    //make shared_ptr to member with aliasing constructor
    std::shared_ptr<Foo> foo_p(bar_p, &bar_p->foo);
    assert(bar_p->foo.shared_from_this()); //fail! throws bad_weak_ptr
}

不幸的是,它没有按预期工作(至少在 GCC 4.8.2 中)。我查看了代码,似乎别名构造函数根本不调用__enable_shared_from_this_helper(),这是shared_from_this()正常工作所必需的。

有人知道为什么会这样设计吗?从 shared_from_this 返回 shared_ptr 给成员有什么问题吗?

【问题讨论】:

    标签: c++ c++11 std shared-ptr


    【解决方案1】:

    [util.smartptr.shared.const]

    template&lt;class Y&gt; shared_ptr(const shared_ptr&lt;Y&gt;&amp; r, T* p) noexcept;

    效果:构造一个shared_ptr 实例,该实例存储 p 并与r共享所有权。

    当您调用别名构造函数时,

    foo_p 没有 bar_p-&gt;foo 的所有权,在这种情况下,这是一件非常的好事,因为否则它会在销毁时尝试 delete。

    [util.smartptr.enab]

    shared_ptr&lt;T&gt; shared_from_this();

    shared_ptr&lt;T const&gt; shared_from_this() const;

    要求:[...]至少有一个 shared_ptr 实例 p 拥有 &amp;t。

    由于bar_p-&gt;foo 不属于至少一个shared_ptr,因此您最终会出现未定义的行为,gcc 会抛出bad_weak_ptr,但它没有义务做任何有用的事情。

    【讨论】:

    • 好的,这就是行为,但这样做的理由是什么?为什么shared_from_this() 不要求至少有一个shared_ptr 存储 p?
    • 因为绝对没有办法计算谁拥有一个原始指针以及它打算用它做什么,你似乎认为shared_ptr 知道或关心p 的生命周期,更不用说它是可能涉及也可能不涉及另一个 shared_ptr 实例的层次结构的一部分。
    • 我假设,只有当 p 的生命周期由 r 保证时,shared_ptr 的别名构造函数才被正确使用(就像 p 指向由 @ 指向的结构的成员时一样987654344@)。在这种情况下,shared_ptr 间接关心p 的生命周期。在其他情况下,shared_ptr 无论如何都是无效的。
    • 我支持 peper0。我看不出有任何技术上的原因无法做到这一点。 @user657267:别名构造函数确实与r共享控制块,这是我们关心的生命周期,因为p的生命周期直接与r相关联。我认为填充 p 的 shared_from_this 以引用所有者的生命周期会很有帮助。
    猜你喜欢
    • 2015-08-05
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 2017-05-02
    相关资源
    最近更新 更多