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****进行"借尸还魂"(共享控制块),但切记不可在构造函数中使用。

相关推荐
M78佐菲3 小时前
Linux学习笔记:TCP协议
linux·笔记·学习·tcp/ip·算法
恋恋西风3 小时前
C++ 理解 std::thread 在单核和多核上的行为差异
开发语言·c++
Brilliantwxx3 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
噜~噜~噜~3 小时前
操作系统笔记-2.3.5.1.1生产者-消费者问题
笔记·操作系统
BizzZ_4 小时前
C++(22)——类型转换和IO流
开发语言·c++
青梅味猪大肠6 小时前
【深入浅出C++】为什么虚表指针可以解决菱形继承
开发语言·c++
Lhan.zzZ7 小时前
QML 组件库:VS2022 + Qt 静态库方案
开发语言·c++·qt·visual studio
Huathy-雨落江南,浮生若梦7 小时前
Caddy 学习笔记 - 反向代理与 IP 封禁
笔记·学习·tcp/ip
谢白羽8 小时前
SGLang的AWQ量化笔记
笔记·python·sglang
噜~噜~噜~9 小时前
操作系统笔记-2.3.5.2 读者-写者问题
笔记·操作系统