c++oding="utf-8" ?>
直接传 this 给 shared_ptr 构造函数会崩溃,因为对象未被 shared_ptr 管理时,多个独立 shared_ptr 会各自维护控制块,导致双重析构或 std::bad_weak_ptr 异常;正确做法是始终用 make_shared 创建对象并继承 enable_shared_from_this。

为什么直接传 this 给 shared_ptr 构造函数会崩溃
因为 enable_shared_from_this 不是魔法,它不控制对象生命周期,只提供从已有 shared_ptr 派生新实例的能力。如果你还没用 make_shared 或 shared_ptr 构造函数管理对象,就调用 shared_from_this(),会抛出 std::bad_weak_ptr 异常;更危险的是,若手动用 new 创建对象后传 this 给 shared_ptr(比如 shared_ptr<t>(this)</t>),会导致双重析构 —— shared_ptr 和原始指针各自 delete 一次。
- 根本原因:一个对象只能由一个
shared_ptr的控制块管理,多个独立的shared_ptr指向同一裸指针会各自维护计数器,互不知情 - 典型错误写法:
shared_ptr<myclass>(this)</myclass>出现在成员函数里,尤其在回调、lambda 或异步任务中偷偷这么干 -
enable_shared_from_this的weak_ptr成员只在对象被shared_ptr管理后才被初始化,否则是空的
必须用 make_shared 构造对象,且不能脱离 shared_ptr 生命周期
安全传递的前提是:对象从诞生起就处于 shared_ptr 管理之下。这意味着你不能用 new MyClass,也不能把栈对象取 this 传出去 —— 栈对象没有控制块,shared_from_this() 必然失败。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 正确姿势:所有实例都通过
auto ptr = make_shared<myclass>()</myclass>创建 - 类定义必须继承
enable_shared_from_this<myclass></myclass>,且模板参数必须精确匹配类型(不能是基类) - 如果类有多个继承路径或模板特化,确保
enable_shared_from_this在最派生类上显式继承,否则shared_from_this()返回的可能是错误类型的shared_ptr - 不要在构造函数体里调用
shared_from_this()—— 此时控制块尚未完全建立,某些标准库实现(如 libstdc++ 旧版本)可能未初始化内部weak_ptr
在回调或异步上下文中安全捕获 shared_from_this()
常见需求:注册一个 lambda 做异步回调,需要访问对象状态,又怕对象提前销毁。这时不能捕获 this,而要捕获 shared_from_this() 的结果,确保引用计数延长生命周期。
void MyClass::start_async() {
auto self = shared_from_this(); // 在调用前确保 this 已被 shared_ptr 管理
some_async_library.run([self]() {
// self 保证对象存活,可安全访问成员
self->do_work();
});
}
- 务必在 lambda 外先调用
shared_from_this()并赋给局部变量,再捕获该变量;直接在捕获列表写[self = shared_from_this()]是 OK 的,但不能写[this]或[=](后者可能隐式捕获裸this) - 如果异步操作可能长时间挂起,而对象在此期间被外部释放,
self仍有效 —— 它只是延长了生命周期,不会阻止正常析构 - 注意循环引用风险:如果
self被存进某个长期持有的容器(如全局 map、信号槽连接),而该容器又被对象自身持有,就会导致泄漏。此时应改用weak_from_this()+ 手动 lock
什么时候该用 weak_from_this() 而不是 shared_from_this()
当你无法确定对象是否还活着,或者想避免延长生命周期(比如观察者模式、缓存索引、事件总线订阅),就要用 weak_from_this()。它返回 weak_ptr,不增加引用计数,后续需显式 lock() 获取临时 shared_ptr。
void MyClass::register_as_observer() {
auto weak_self = weak_from_this(); // 安全,即使 this 尚未被 shared_ptr 管理也不崩溃(返回空 weak_ptr)
event_bus.subscribe([weak_self](Event e) {
if (auto self = weak_self.lock()) { // lock() 成功才说明对象仍在
self->handle_event(e);
}
// 如果 lock() 失败,说明对象已析构,直接忽略
});
}
-
weak_from_this()即使在对象未被shared_ptr管理时也安全(返回空weak_ptr),而shared_from_this()会抛异常 - 所有跨作用域、跨线程、不可控生命周期的引用场景,优先考虑
weak_ptr+lock()模式 - 注意
lock()返回的shared_ptr只在当前作用域有效;不要把它存为成员变量或长期持有,否则又变相延长了生命周期
this 的本质不是“怎么传”,而是“谁在管它的生命”。一旦脱离 shared_ptr 的统一管理,任何基于 enable_shared_from_this 的操作都会失效或危险。很多人卡在“为什么明明继承了却 still get bad_weak_ptr”,其实问题不出在调用方式,而出在对象压根没被 shared_ptr 构造过。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










