为什么 std::shared_ptr 的别名构造函数不初始化 std::enabled_shared_from_this?

Why doesn't aliasing constructor of std::shared_ptr initialize std::enabled_shared_from_this?

本文关键字:std shared from enabled 初始化 this 别名 ptr 为什么 构造函数      更新时间:2023-10-16

请考虑以下代码:

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退还给会员有什么问题吗?

[util.smartptr.shared.const]

template<class Y> shared_ptr(const shared_ptr<Y>& r, T* p) noexcept;

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

当您调用别名构造函数时,foo_p 不拥有bar_p->foo,在这种情况下这是一件非常好的事情,否则它会尝试在销毁时delete它。

[util.smartptr.enab]

shared_ptr<T> shared_from_this();

shared_ptr<T const> shared_from_this() const;

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

由于bar_p->foo不属于至少一个人,shared_ptr你最终会得到未定义的行为,gcc 会抛出bad_weak_ptr但它没有义务做任何有用的事情。