当包含对象定义的活跃栈弹出时,析构函数是否会被调用?C++代码疑问
这是C++的**返回值优化(RVO, Return Value Optimization)**导致的,这是编译器允许的一种性能优化手段,用于减少临时对象的创建和销毁开销。
首先纠正一个小问题:你的预期输出顺序本身有误——Complex temp;语句会先调用构造函数,所以未优化情况下,应该先打印default ctor called,再打印----inside function----,之后才是函数返回时的析构。
回到核心问题:你的代码中编译器做了RVO优化,没有在getComplex函数的栈帧里单独创建temp对象,而是直接在main函数中c的内存位置构造这个对象。也就是说,temp和c本质是同一个对象,因此temp的生命周期和c完全绑定,直到main函数执行完毕才会调用析构函数,这就是你看到析构函数在----inside main----之后才打印的原因。
如何验证优化效果?
如果你想看到未优化的预期行为,可以关闭返回值优化。在GCC或Clang编译器中,使用-fno-elide-constructors编译选项:
g++ -fno-elide-constructors your_code.cpp -o test
运行编译后的程序,你会看到类似如下输出:
default ctor called ----inside function---- dctor called ----inside main---- dctor called
这里的两次dctor called分别对应:函数内temp在返回时析构,以及main中c在程序结束时析构。(因为编译器会生成默认拷贝构造函数用于返回对象,但默认拷贝构造没有打印语句,所以你看不到拷贝构造的输出)
补充说明
返回值优化是C++标准明确允许的,即便它改变了构造/析构的打印顺序,也不会改变程序的语义。这种优化是编译器自动进行的,目的是提升程序性能,所以在依赖对象构造/析构时机的场景中,需要注意这种优化的存在。
内容的提问来源于stack exchange,提问作者Run

