You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; 
    }
};

补充完逻辑后,程序的实际执行输出顺序为:

  1. 执行第一个临时对象构造:打印Hello Marc
  2. 第一个临时对象析构:先执行delete myname,打印See you soon Marc,再打印Exit
  3. 执行第二个临时对象构造:打印Hello Alex
  4. 第二个临时对象析构:先执行delete myname,打印See you soon Alex,再打印Exit

内容的提问来源于stack exchange,提问作者Ronyco123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 14:54:05