不能直接在成员函数里调用 delete this,因为会导致未定义行为:对象销毁后栈帧未退出,后续代码访问已释放内存;若对象在栈上或由 shared_ptr 管理则崩溃。

为什么不能直接在成员函数里调用 delete this
直接写 delete this 看似能“自我销毁”,但极大概率引发未定义行为。常见错误包括:对象被销毁后,函数栈帧还没退出,后续代码(比如隐式析构、返回值处理、甚至 return 之后的清理)仍试图访问已释放内存;若该对象是栈上分配或通过 std::shared_ptr 管理,delete this 会直接崩溃。
用 std::shared_ptr + enable_shared_from_this 是最稳妥的方案
这是 C++11 起官方推荐的、线程安全且语义清晰的做法。核心在于:让类继承 std::enable_shared_from_this<t></t>,并通过 shared_from_this() 获取自身有效的 std::shared_ptr,再在合适时机移交所有权并触发销毁。
- 必须确保对象**已经由
std::make_shared<t></t>构造**(否则shared_from_this()抛std::bad_weak_ptr) - 调用
shared_from_this()前不能已存在裸指针或unique_ptr持有该对象 - 销毁逻辑应封装为异步或延迟操作,例如:把
shared_ptr移交给一个延时执行器、事件循环或工作队列,避免在成员函数内立即销毁 - 示例片段:
class SelfDestructible : public std::enable_shared_from_this<selfdestructible> { public: void scheduleSelfDestruct() { auto self = shared_from_this(); // 安全获取共享所有权 std::thread([self] { std::this_thread::sleep_for(100ms); // 此时 self 离开作用域,引用计数减一,可能触发析构 }).detach(); } };</selfdestructible>
手动管理时,必须严格区分“销毁请求”和“实际销毁”
如果因约束无法用 shared_ptr(如嵌入式、性能敏感场景),可将销毁拆成两步:标记 + 外部协调。类本身不执行 delete,而是通知外部管理者(如容器、工厂、事件调度器)来回收。
- 在类中加一个
bool m_shouldDie{false}标志位,由成员函数设置 - 外部循环(如游戏主循环、消息泵)定期检查所有对象的
m_shouldDie,统一调用delete或移交内存池 - 禁止在
setShouldDie()内调用delete this,哪怕加了if (m_shouldDie) return;也不行——因为调用栈尚未展开完毕 - 若对象位于容器中(如
std::vector<:unique_ptr>></:unique_ptr>),外部销毁时需从容器中erase对应项,防止悬空指针
析构函数里千万别做“自我销毁”的事
析构函数本就是销毁过程的终点,此时对象内存正被回收,任何尝试延长生命周期或重新获取指针的行为都无效且危险。
- 不要在析构函数中调用
shared_from_this()—— 引用计数已为零或正在归零 - 不要在析构函数中启动新线程、发信号、调用回调,除非你 100% 确保这些操作不访问
*this的任何成员 - 若需“销毁后通知”,应提前注册弱引用回调(如
std::weak_ptr+lock()检查),并在外部观察者中处理
真正难的不是写 delete this,而是判断“谁拥有这个对象的生命周期控制权”。一旦混淆,问题会出现在随机时间点,很难复现。所以优先走 shared_ptr 路线,实在不行就推给外部统一管理。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











