C++中类动态创建另一类实例并存储指针,为何目标类析构函数未被调用
问题核心根因
你对C++堆内存对象的生命周期存在两个认知偏差,直接导致了看不到Name类析构函数触发的现象:
new关键字创建的对象会被分配在堆内存上,不会被程序自动析构。C只会自动析构栈上的对象(比如函数内的局部变量、临时对象);堆对象的生命周期完全需要开发者手动管控,只有对对象指针显式调用delete时,才会触发对应对象的析构函数。哪怕程序最终退出,操作系统只会在进程结束时回收整块进程的内存资源,这个过程是系统层面的裸内存回收,根本不会执行C层面的对象析构逻辑。- 你在
Person类的析构函数里,完全没有对持有的myname指针执行delete操作:哪怕Person对象本身的析构逻辑(也就是打印"Exit"的部分)因为临时对象的销毁正常触发了,它内部指向的堆上Name对象因为从来没被释放,对应的~Name()根本没有执行入口,自然不会打印告别信息。 - 你在
main函数里写的Person("Marc");这类代码,创建的是栈上的临时Person对象,这类临时对象会在所在语句执行结束时自动触发自身析构,但这个析构动作和它内部持有的堆上Name对象的生命周期没有任何绑定。
可行的修正方案
- 最直接的手动内存管理修正:在
Person类的析构函数中补充delete myname;逻辑,当Person对象析构时,就会同步释放它持有的Name对象,触发对应的析构函数。注意这种写法需要遵循C++三/五法则,额外处理拷贝构造、拷贝赋值的逻辑,否则会触发重复释放内存的崩溃问题。 - 更稳妥的现代C++写法:尽量避免用裸指针持有堆对象,直接在
Person类中以值的形式存储Name成员,从根源上消除手动内存管理的需求。 - 如果确实需要以指针形式持有成员,用标准库提供的智能指针(比如
std::unique_ptr<Name>)替代裸指针,当Person对象析构时,智能指针会自动完成指向对象的释放,不需要手动写delete。
修正后的核心代码示例
class Person { private: Name* myname; public: Person(string name) { myname = new Name(name); } ~Person() { // 补充释放myname的逻辑 delete myname; std::cout << "Exit" << std::endl; } };
补充完逻辑后,程序的实际执行输出顺序为:
- 执行第一个临时对象构造:打印
Hello Marc - 第一个临时对象析构:先执行
delete myname,打印See you soon Marc,再打印Exit - 执行第二个临时对象构造:打印
Hello Alex - 第二个临时对象析构:先执行
delete myname,打印See you soon Alex,再打印Exit
内容的提问来源于stack exchange,提问作者Ronyco123
相关产品推荐
相关产品推荐

