You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Option1调用shared_from_this触发bad_weak_ptr崩溃,Option2正常?

为什么Option1调用shared_from_this()触发bad_weak_ptr崩溃,Option2却正常?

Option1调用shared_from_this()时会因bad_weak_ptr导致崩溃,Option2则可正常运行。二者唯一区别是克隆对象的创建位置:一种在Clone()函数内,另一种在创建克隆的shared_ptr语句中。看似两种情况都满足shared_from_this()要求的“调用时已有shared_ptr持有当前对象所有权”的条件,实际差异出在enable_shared_from_this的初始化逻辑上。

问题代码

class Base
{
public:
    virtual Base* Clone() = 0;
};

class Derived : public Base, public std::enable_shared_from_this<Derived>
{
public:
    Base* Clone() override
    {
        return new Derived(*this);
    }
    void test()
    {
        std::shared_ptr<Derived> ptr = shared_from_this();
    }
};

int main()
{
    std::shared_ptr<Base> obj = std::make_shared<Derived>();
    //std::shared_ptr<Base> clone = std::shared_ptr<Base>(obj->Clone()); // option 1(崩溃)
    std::shared_ptr<Base> clone = std::shared_ptr<Base>(new Derived(*std::static_pointer_cast<Derived>(obj))); // option 2(正常)
    std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(clone);
    derived->test();

    return 0;
}

核心原因:enable_shared_from_this的初始化依赖指针静态类型

std::enable_shared_from_this内部靠一个weak_ptr跟踪对象的shared_ptr持有者,这个weak_ptr只会在第一个指向对象的shared_ptr构造时初始化,且初始化的前提是:shared_ptr的构造函数能识别到对象实际类型继承了enable_shared_from_this。

Option1崩溃的原因

  1. obj->Clone()返回的是Base*类型指针(虽然实际指向Derived对象)。
  2. 用这个Base*构造std::shared_ptr<Base>时,编译器只能看到Base类型——而Base没有继承enable_shared_from_this,因此shared_ptr的构造函数不会去初始化Derived对象内部的enable_shared_from_this weak_ptr。
  3. 后续调用test()时,shared_from_this()尝试从未初始化的weak_ptr生成shared_ptr,直接触发bad_weak_ptr异常。

Option2正常的原因

  1. new Derived(...)生成的是Derived*类型指针,随后隐式转换为Base*传给std::shared_ptr<Base>的构造函数。
  2. shared_ptr的构造函数是模板实现,能推导传入指针的实际类型是Derived*,发现Derived继承了enable_shared_from_this<Derived>,于是会正确初始化对象内部的weak_ptr。
  3. 调用test()时,shared_from_this()可以从已初始化的weak_ptr生成合法的shared_ptr,因此正常运行。

修复Option1的正确方式

要让Option1正常工作,需要让Clone()返回的指针能让shared_ptr识别到实际类型,最简单的方法是修改Clone()返回std::shared_ptr<Base>:

class Base
{
public:
    virtual std::shared_ptr<Base> Clone() = 0;
};

class Derived : public Base, public std::enable_shared_from_this<Derived>
{
public:
    std::shared_ptr<Base> Clone() override
    {
        return std::make_shared<Derived>(*this);
    }
    void test()
    {
        std::shared_ptr<Derived> ptr = shared_from_this();
    }
};

int main()
{
    std::shared_ptr<Base> obj = std::make_shared<Derived>();
    std::shared_ptr<Base> clone = obj->Clone(); // 现在可正常运行
    std::shared_ptr<Derived> derived = std::static_pointer_cast<Derived>(clone);
    derived->test();

    return 0;
}

内容的提问来源于stack exchange,提问作者Notrum666

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:05:28