1. 核心痛点:为什么要用它?
问题场景: 当我们需要在类的成员函数内部 获取当前对象的 shared_ptr(即"把我自己交给别人管理")时。
错误做法: 直接使用 this 指针创建 shared_ptr。
// ❌ 绝对禁止!
std::shared_ptr<T> sp(this);
- 后果: 导致 Double Free(重复释放)。
- 原因: 这样会创建一个新的控制块 。导致两个独立的
shared_ptr管理同一块内存,引用计数互不通气,最终分别析构时都会尝试delete对象。
正确做法: 使用 shared_from_this()。
- 作用: 它查找并返回已存在的控制块,确保引用计数正确增加,而不是新建控制块。
2. 标准用法 (代码模板)
使用时需满足两个语法条件:
-
类必须公有继承 (public) 自
std::enable_shared_from_this<T>。 -
对象必须由
shared_ptr管理。#include <memory>
class Worker : public std::enable_shared_from_this<Worker> { // 1. 继承
public:
void joinWorkGroup() {
// 2. 获取自己的 shared_ptr
std::shared_ptr<Worker> self = shared_from_this();// 业务逻辑...}
};int main() {
// 3. 必须使用 shared_ptr 创建对象
auto w = std::make_shared<Worker>();
w->joinWorkGroup();
return 0;
}
3. 底层原理 (面试考点)
enable_shared_from_this 是如何工作的?
- 内部成员: 该类内部隐藏了一个成员变量
mutable std::weak_ptr<T> weak_this;。 - 延迟初始化:
-
- 这个
weak_this不在构造函数中初始化。 - 它是在外部第一次 创建
shared_ptr<T>(如make_shared)时,由shared_ptr的构造函数检测并初始化的。
- 这个
- 调用机制:
-
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****进行"借尸还魂"(共享控制块),但切记不可在构造函数中使用。