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

C++静态与动态对象析构顺序及delete后sizeof问题咨询

C++静态与动态对象的析构函数调用及sizeof问题解析

已知知识点:静态分配的对象会自动调用析构函数,动态分配的对象需手动调用析构函数。

疑问与问题

  • 疑问1:当同时创建一个静态对象和一个动态对象时,它们的析构函数会在对象超出作用域时同时被调用吗?
  • 具体问题1:为何动态对象的析构函数先被调用?
  • 具体问题2:为何调用delete销毁动态对象后,其sizeof结果仍非零?

代码示例

#include <bits/stdc++.h>
using namespace std;

// Destructor (NO return type & NO input parameter)
class Hero {
public:
    int health;
    
    Hero() { // constructor
        cout << "constructor is called" << endl;
    }

    
    ~Hero() {// destructor
        cout << "destructor is called" << endl;
    }
};

int main(){
    Hero h1; // static allocation (automatically call destructor)

    Hero *h2 = new Hero; // dynamic allocation (manually call destructor)
    delete h2;

    cout << "Size (static)  : " << sizeof(h1) << endl;
    cout << "Size (dynamic) : " << sizeof(h2) << endl;
    return 0;
}

输出显示动态对象析构函数先执行,且动态对象指针的sizeof值非零。


问题解答

1. 动态对象的析构函数为何先被调用?

你的代码里,动态对象h2是通过new在堆上分配的,随后你主动调用了delete h2——这个操作会立刻触发动态对象的析构函数,释放它占用的堆内存。而静态对象h1是分配在栈上的,它的析构函数要等到**当前作用域结束时(也就是main函数执行完return 0之后)**才会自动调用。

代码的实际执行顺序是:

  • 创建静态对象h1,调用构造函数
  • 创建动态对象h2,调用构造函数
  • 执行delete h2,立即调用动态对象的析构函数
  • 输出两个sizeof结果
  • main函数结束,静态对象h1超出作用域,调用其析构函数

这就是你看到动态对象析构函数先执行的原因。

2. 调用delete销毁动态对象后,其sizeof结果仍非零?

这里你搞混了动态对象本身和指向动态对象的指针的区别:

  • h2是一个指针变量,它存的是动态对象在堆内存中的地址,不是对象本身。
  • sizeof(h2)计算的是指针变量的大小,和指针指向的对象有没有被销毁完全没关系。在32位系统里指针大小通常是4字节,64位系统是8字节——哪怕你调用delete释放了对象,指针变量本身依然存在(只是变成了野指针,指向的内存已无效),它的大小始终是当前系统下指针的固定长度。

而sizeof(h1)计算的是静态对象h1的实际大小,因为h1是Hero类的实例,包含一个int成员,所以大小等于sizeof(int)(通常4字节)。

3. 静态与动态对象的析构函数是否会在对象超出作用域时同时被调用?

不会。静态分配的栈对象,析构函数会在作用域结束时自动调用;而动态分配的堆对象,析构函数只有在手动调用delete(或者用智能指针这类自动管理工具)时才会触发,和作用域结束没有直接关联。如果不手动调用delete,动态对象的析构函数永远不会被执行,会造成内存泄漏。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 05:35:12