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

C++中对象超出作用域时会调用析构函数吗?代码存疑

为什么你的C++代码输出不符合预期?

嘿,这个问题其实是C++里一个经典的陷阱——最令人头疼的解析(Most Vexing Parse),我来给你拆解清楚:

核心问题:函数声明 vs 对象定义

你代码里的这两行是关键坑:

C c0();
D d0();

你以为这是创建C和D类的无参对象,但在C++的语法规则里,这其实是函数声明:

  • C c0(); 声明了一个名为c0的函数,它没有参数,返回值类型是C
  • D d0(); 声明了一个名为d0的函数,它没有参数,返回值类型是D

这意味着这两行根本没有创建任何对象,自然不会调用构造函数,后续也不会有析构行为。

逐行分析代码的执行流程

我们来走一遍main函数的执行逻辑:

  1. C c0();:函数声明,无对象创建,无构造/析构调用
  2. C* c1 = new C();:动态分配C对象,调用C的构造函数(初始化s.t=7)
  3. D d0();:函数声明,无对象创建,无构造/析构调用
  4. D d1(42);:在栈上创建D对象,调用带参构造函数(初始化s.t=42)
  5. std::cout << __LINE__ << std::endl;:输出当前行号(假设这是代码的第19行,输出19)
  6. delete c1;:释放动态分配的C对象,调用C的析构函数,输出bye C
  7. std::cout << __LINE__ << std::endl;:输出当前行号(假设是第21行,输出21)
  8. main函数结束:栈上的D d1对象被销毁,调用D的析构函数,输出bye D(42)

所以最终的输出顺序是:

19
bye C
21
bye D(42)

如何修正代码?

如果想创建无参对象,要避免函数声明的语法:

  • 对于有默认构造函数的类(比如C),直接写:C c0; 或者 C++11及以后用C c0{};
  • 对于没有默认构造函数的类(比如D,它只有带int参数的构造函数),必须传入参数,比如:D d0(10); 或者D d0{10};

修正后的main函数示例:

int main() {
    C c0; // 创建C类对象,调用默认构造
    C* c1 = new C();
    D d0(10); // 创建D类对象,传入参数10
    D d1(42);
    std::cout << __LINE__ << std::endl;
    delete c1;
    std::cout << __LINE__ << std::endl;
}

这时候的输出会包含c0和d0的析构信息,符合你的预期。

内容的提问来源于stack exchange,提问作者not-a-user

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:05:37