shared_from_this

1. 核心痛点:为什么要用它?

问题场景: 当我们需要在类的成员函数内部 获取当前对象的 shared_ptr(即"把我自己交给别人管理")时。

错误做法: 直接使用 this 指针创建 shared_ptr。

复制代码
// ❌ 绝对禁止!
std::shared_ptr<T> sp(this);
  • 后果: 导致 Double Free(重复释放)。
  • 原因: 这样会创建一个新的控制块 。导致两个独立的 shared_ptr 管理同一块内存,引用计数互不通气,最终分别析构时都会尝试 delete 对象。

正确做法: 使用 shared_from_this()。

  • 作用: 它查找并返回已存在的控制块,确保引用计数正确增加,而不是新建控制块。

2. 标准用法 (代码模板)

使用时需满足两个语法条件:

  1. 类必须公有继承 (public) 自 std::enable_shared_from_this<T>。

  2. 对象必须由 shared_ptr 管理。

    #include

    class Worker : public std::enable_shared_from_this { // 1. 继承
    public:
    void joinWorkGroup() {
    // 2. 获取自己的 shared_ptr
    std::shared_ptr self = shared_from_this();

    复制代码
     // 业务逻辑...

    }
    };

    int main() {
    // 3. 必须使用 shared_ptr 创建对象
    auto w = std::make_shared();
    w->joinWorkGroup();
    return 0;
    }


3. 底层原理 (面试考点)

enable_shared_from_this 是如何工作的?

  1. 内部成员: 该类内部隐藏了一个成员变量 mutable std::weak_ptr<T> weak_this;。
  2. 延迟初始化:
    • 这个 weak_this不在构造函数中初始化。
    • 它是在外部第一次 创建 shared_ptr<T>(如 make_shared)时,由 shared_ptr 的构造函数检测并初始化的。
  1. 调用机制:
    • shared_from_this() 本质上就是执行 return weak_this.lock();。
    • 它利用内部保存的弱引用,升级为一个新的强引用返回。

4. 三大"死亡陷阱" (易错点)

❌ 陷阱一:在构造函数中调用

  • 现象: 抛出 std::bad_weak_ptr 异常,程序崩溃。
  • 原因: 构造函数执行时,对象刚刚建立,外部的 shared_ptr 还没有机会初始化内部的 weak_this。此时 weak_ptr 是空的。
  • 解决: 使用"二段式构造"(先构造,再调用 init 函数),或者在其他成员函数中使用。

❌ 陷阱二:对象不是 shared_ptr 管理的

  • 场景: 对象在栈 上,或者通过 new 出来的裸指针。

    Worker w;
    w.joinWorkGroup(); // 崩溃!

  • 原因: 没有外部 shared_ptr 介入,内部的 weak_this 永远不会被初始化,一直是空的。

❌ 陷阱三:私有继承 (Private Inheritance)

  • 场景: class Worker : std::enable_shared_from_this<Worker> (默认为 private)。
  • 原因: shared_ptr 的构造函数无法访问基类的成员,导致无法初始化 weak_this。必须显式写出 public。

5. 一句话总结

shared_from_this****是为了解决"裸指针 this****变 shared_ptr****导致的多重释放"问题,其原理是利用内部隐藏的 weak_ptr****进行"借尸还魂"(共享控制块),但切记不可在构造函数中使用。

相关推荐
dialect_10 分钟前
CODEFORCES ROUND 1127 DIV2
开发语言·c++·算法
乐橙开放平台31 分钟前
离岗检测怎么实现?通过客流相机或 AI 摄像头识别岗位区域无人状态,再推送告警消息
人工智能·笔记·后端·数码相机·物联网·自动化·音视频
悠仁さん8 小时前
【C++】AVL 树
c++
wuminyu9 小时前
JVM规范学习总结:解释器与JIT编译器如何处理JVM字节码
java·linux·c语言·jvm·c++
小徐不徐说9 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
ragnwang9 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
蒸蒸yyyyzwd10 小时前
AI应用相关可能的面试问题
笔记
充值内卷11 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
叼烟扛炮11 小时前
[Git 实战] 学习笔记:从生成 SSH 密钥到解决 TortoiseGit 推送报错全指南
linux·运维·笔记·git·学习
蒸蒸yyyyzwd12 小时前
学习笔记 八股手撕
笔记·学习