C++函数局部变量销毁时机问询(含C++14与C++17差异)
C++局部非静态对象销毁时机解析
问题1(C++14及更早版本)
你的理解是正确的。在C++14及更早版本中,无优化情况下函数返回对象的流程是:
- 先基于函数内的局部对象创建返回临时对象;
- 临时对象构造完成后,函数的局部变量按声明逆序销毁(示例中先销毁
y,再销毁x); - 最后临时对象参与赋值操作,赋值完成后临时对象自身才会销毁。
这和你看到的输出完全匹配:y的析构函数先输出quitting f(),之后才执行assignment赋值操作。
问题2(C++17及更高版本)
你的猜测不完全准确,核心要结合C++17对prvalue的新规则理解:
C++17重新定义了prvalue,它不再是“临时对象的雏形”,而是直接代表对象的初始化操作。当你写return X(z);时,这个prvalue会直接将X对象构造在最终需要它的内存位置——也就是main()中用于赋值的临时对象内存,而非中间生成额外的临时对象。
具体执行流程:
- 调用
f2()时,返回f1()的prvalue不会触发f1()局部对象提前销毁; - 执行
f1()的return X(z);时,X对象直接在f2()返回值对应的物化位置(即main()的赋值临时对象内存)完成构造,输出constructing X; X构造完成后,f1()的局部变量(z和Ya)按逆序销毁,输出quitting f1();- 接着
f2()的局部变量Yb销毁,输出quitting f2(); - 最后临时对象参与赋值操作,输出
assignment。
关键点:函数的局部变量会在返回语句中prvalue对应的最终对象构造完成后销毁,而非prvalue传递过程中。因此z在X对象构造完成后才销毁,完全能满足X(Z)构造函数的需求,不会出现对象依赖已销毁变量的问题。
如果写成X x = f2();,f2()的prvalue会直接物化到x的内存中,同样是f1()和f2()的局部变量在各自返回语句的对象构造完成后依次销毁,之后x就完成了初始化。
内容的提问来源于stack exchange,提问作者CPPL
相关产品推荐
相关产品推荐

