C++对象调用成员方法删除自身是否可行?代码行为解析
对象自销毁的行为疑问与分析
一、裸指针实现的崩溃原因
当类对象调用成员方法时,若方法内部销毁对象本身,裸指针实现会直接崩溃,核心原因是销毁对象后,方法返回时会访问已失效的指针上下文。
裸指针实现代码
class Foo { public: virtual void Run() { printf("Entering callback\n"); RunSomeCallback(); printf("We're back from callback\n"); } virtual void RunSomeCallback() = 0; virtual ~Foo() { printf("We're Destroyed\n"); } }; Foo* f = nullptr; void DestroyFoo(); class Bar : public Foo { public: virtual void RunSomeCallback() { printf("Inside callback\n"); DestroyFoo(); } }; void DestroyFoo() { printf("Deleting foo\n"); delete f; } int main() { f = new Bar(); f->Run(); return 0; }
崩溃逻辑:
- 调用
f->Run()后进入Run方法,执行RunSomeCallback(); RunSomeCallback()内部调用DestroyFoo(),执行delete f释放对象内存,析构函数执行;- 当
RunSomeCallback()返回时,程序试图回到Run方法继续执行剩余代码,但此时this指针已指向被释放的内存,访问该上下文属于未定义行为,直接触发崩溃。
二、shared_ptr实现的行为分析
改用std::shared_ptr后代码可运行,但这种行为仍属于未定义行为,只是巧合未触发崩溃。
shared_ptr实现代码
class Foo { public: virtual void Run() { printf("Entering callback\n"); RunSomeCallback(); printf("We're back from callback\n"); } virtual void RunSomeCallback() = 0; virtual ~Foo() { printf("We're Destroyed\n"); } }; std::shared_ptr<Foo> f; void DestroyFoo(); class Bar : public Foo { public: virtual void RunSomeCallback() { printf("Inside callback\n"); DestroyFoo(); } }; void DestroyFoo() { printf("Deleting foo\n"); f = nullptr; } int main() { f = std::make_shared<Bar>(); f->Run(); return 0; }
实际打印顺序
Entering callback Inside callback Deleting foo We're Destroyed We're back from callback
行为解读
- 执行
f = nullptr时,shared_ptr引用计数降为0,触发对象析构; - 此时
Run方法未执行完毕,但剩余代码仅为printf,未访问对象成员或调用虚函数,因此未触发崩溃; - 这只是偶然情况,标准未保证该行为的安全性。若
Run剩余代码访问对象成员或调用虚函数,同样会触发未定义行为导致崩溃。
三、对象销毁时机的明确结论
对象的析构函数执行完成后,对象就已被彻底销毁,不存在“等到所有成员方法执行完成后才真正销毁”的情况。shared_ptr例子中析构函数先执行但代码仍能运行,只是因为剩余代码未触碰已销毁对象的资源,不代表该行为合法。
内容的提问来源于stack exchange,提问作者Kayla
相关产品推荐
相关产品推荐

