C++:临时论证的生命周期?

sho*_*osh 65 c++ destructor

当创建a的新实例MyClass作为函数的参数时,如下所示:

class MyClass
{
  MyClass(int a);
};    

myFunction(MyClass(42));
Run Code Online (Sandbox Code Playgroud)

该标准是否使得任何被授权者都能获得析构函数的时间安排?
具体来说,我可以假设在调用之后的下一个语句之前调用它myFunction()吗?

sbi*_*sbi 106

临时对象在它们所属的完整表达结束时被销毁.

完整表达式是不是某个其他表达式的子表达式的表达式.通常,这意味着它在端部处;(或)if,while,switch等等)表示的语句的末尾.在您的示例中,它是函数调用的结束.

请注意,您可以通过将临时数据绑定到const引用来延长它们的生命周期.这样做会将其生命周期延长到参考的生命周期:

MyClass getMyClass();

{
  const MyClass& r = getMyClass(); // full expression ends here
  ...
} // object returned by getMyClass() is destroyed here
Run Code Online (Sandbox Code Playgroud)

如果您不打算更改返回的对象,那么这是保存复制构造函数调用(与之相比MyClass obj = getMyClass();)的一个很好的技巧,以防未应用返回值优化.不幸的是,它并不是很有名.(我认为C++ 11的移动语义会使它不那么有用.)

  • 我没有意识到你可以使用const引用延长临时对象的寿命.很高兴知道! (3认同)
  • 在C++ 11中,右值引用也延长了临时值的生命周期.但是,出于性能原因,我不担心使用其中任何一个.我希望任何优化编译器在这里应用复制/移动省略,使两个版本编译为相同的代码(按值捕获或绑定到引用). (3认同)
  • 你自己说得对:"完整表达式是一个表达式,不是其他表达式的子表达式." 而在while,if,switch case我们在`(`和`)`之间有一个完整的表达式,因为它们出现的语句不是任何方式的表达式.在你的解释中,`;`的结尾根本就不是一个完整的表达式结尾,因为如果你在while/if或switch之间有一个更大的"表达式".我觉得很容易看出这没有意义:) (2认同)
  • @Johannes:我改了.<sigh>经过这么多年的C++,你每周都会学到一些东西. (2认同)

Ste*_*sop 24

每个人都正确地引用了12.2/3或类似的内容,它们回答了你的问题:

临时对象被破坏,作为评估(词法上)包含创建它们的点的完整表达式的最后一步.

我觉得有趣的是,在我打印标准的下一页中,12.2/4说:

有两种情况,临时表在与完整表达结束时不同的地方被摧毁.

它们都不适用于您的示例,它们都与初始化程序中临时使用有关.但它确实表明你在处理像C++标准这样棘手的野兽时必须保持你的智慧.

  • 哇,谢谢你提到这个"例外".初始化器中的临时工具恰恰是我被咬过的情况. (3认同)

小智 10

该标准确实提供了保证 - 来自第12.2/5节:

在函数调用(5.2.2)中与引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止

但是,在您的代码中,不清楚参数是通过引用还是通过值传递,尽管在某些时候将使用引用引用的复制构造函数.