异步回调中直接用 this 会崩溃,因对象可能已析构导致 this 成悬垂指针;正确做法是继承 std::enable_shared_from_this 并通过 std::make_shared 创建对象,在回调中捕获 shared_from_this() 获取带引用计数的智能指针。

为什么直接用 this 在异步回调里会崩溃
因为异步回调可能在对象已析构后才执行,this 变成悬垂指针。哪怕你用了 std::shared_ptr 管理对象生命周期,this 本身不带引用计数——它只是个裸指针。
典型错误模式:std::async([&] { callback(this); });,捕获 this 后无法阻止对象提前销毁。
解决思路不是“保护 this”,而是让回调能自己持有有效、带引用计数的自身实例。
std::enable_shared_from_this 的正确继承姿势
必须从 std::enable_shared_from_this 公共继承,并且该类**只能通过 std::make_shared(或 std::shared_ptr 构造)创建**,否则 shared_from_this() 会抛 std::bad_weak_ptr。
立即学习“C++免费学习笔记(深入)”;
常见误操作:
- 私有继承
std::enable_shared_from_this - 用
new+std::shared_ptr构造(未调用内部控制块初始化) - 在构造函数体中调用
shared_from_this()(此时控制块尚未建立)
正确写法示例:
struct MyHandler : std::enable_shared_from_this<MyHandler> {
void start() {
// ✅ 此时控制块已就绪
auto self = shared_from_this();
std::async([self] {
self->do_work(); // 安全:self 保证对象存活
});
}
void do_work() { /* ... */ }
};注意:不能写 std::shared_ptr<MyHandler>(this) —— 这会创建第二个独立控制块,导致双重析构。
在 lambda 捕获中传 shared_from_this() 还是 weak_from_this()
优先用 shared_from_this() 捕获,除非回调可能长期挂起、且你明确不想延长对象寿命。
weak_from_this() 适合「尝试性使用」场景,比如定时器回调中先 lock 再判断是否还存活:
void schedule_timeout() {
auto weak_self = weak_from_this();
std::async([weak_self] {
if (auto self = weak_self.lock()) {
self->on_timeout();
} // 否则静默忽略,对象已销毁
});
}但要注意:如果回调逻辑**必须执行**(如资源清理、状态同步),用 weak_from_this() + lock() 就不可靠——它可能返回空,导致逻辑跳过。
多线程下 shared_from_this() 的线程安全边界
shared_from_this() 本身是线程安全的(内部仅读取控制块指针),但它的返回值——即新生成的 std::shared_ptr——需要你确保**拷贝/移动操作不被并发析构干扰**。
真正危险的是这种写法:
void bad_async() {
auto ptr = shared_from_this(); // ✅ OK
std::thread([ptr] {
ptr->do_something(); // ❌ ptr 是栈上局部变量,线程内访问其成员前,主线程可能已析构 ptr
}).detach();
}必须把 shared_ptr **移入 lambda 捕获**(用 [ptr = shared_from_this()] 或 [self = shared_from_this()]),确保该 shared_ptr 的生命周期绑定到 lambda 对象上。
另外,别在析构函数里调用 shared_from_this() —— 控制块可能已被销毁,行为未定义。


















