C++中对象超出作用域时会调用析构函数吗?代码存疑
为什么你的C++代码输出不符合预期?
嘿,这个问题其实是C++里一个经典的陷阱——最令人头疼的解析(Most Vexing Parse),我来给你拆解清楚:
核心问题:函数声明 vs 对象定义
你代码里的这两行是关键坑:
C c0(); D d0();
你以为这是创建C和D类的无参对象,但在C++的语法规则里,这其实是函数声明:
C c0();声明了一个名为c0的函数,它没有参数,返回值类型是CD d0();声明了一个名为d0的函数,它没有参数,返回值类型是D
这意味着这两行根本没有创建任何对象,自然不会调用构造函数,后续也不会有析构行为。
逐行分析代码的执行流程
我们来走一遍main函数的执行逻辑:
C c0();:函数声明,无对象创建,无构造/析构调用C* c1 = new C();:动态分配C对象,调用C的构造函数(初始化s.t=7)D d0();:函数声明,无对象创建,无构造/析构调用D d1(42);:在栈上创建D对象,调用带参构造函数(初始化s.t=42)std::cout << __LINE__ << std::endl;:输出当前行号(假设这是代码的第19行,输出19)delete c1;:释放动态分配的C对象,调用C的析构函数,输出bye Cstd::cout << __LINE__ << std::endl;:输出当前行号(假设是第21行,输出21)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
相关产品推荐
相关产品推荐

