C++:临时参数的生命周期?

问题描述 投票:0回答:4

当创建

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

class MyClass
{
  MyClass(int a);
};    

myFunction(MyClass(42));

标准对析构函数的时间做出任何保证吗?

具体来说,我可以假设它将在调用

myFunction()
之后的下一条语句之前被调用吗?

c++ destructor lifetime temporary-objects
4个回答
122
投票

临时对象在其所属的完整表达式结束时被销毁。

完整表达式是不是其他表达式的子表达式的表达式。通常这意味着它以

;
(或
)
if
while
switch
等)结束,表示语句的结束。在您的示例中,这是函数调用的结束。

请注意,您可以通过将临时对象绑定到

const
引用来延长它们的生命周期。这样做可以将它们的寿命延长到参考的寿命:

MyClass getMyClass();

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

如果您不打算更改返回的对象,那么这是一个保存复制构造函数调用的好技巧(与

MyClass obj = getMyClass();
相比),以防未应用返回值优化。不幸的是它并不是很出名。 (不过,我认为 C++11 的移动语义会使其不太有用。)


29
投票

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

临时对象会被销毁 评估的最后一步 完整表达that(词汇上) 包含他们所在的点 已创建。

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

有两种情况 临时对象被销毁 与结尾不同的点 完整表达。

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


10
投票

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

临时绑定到引用 函数调用中的参数 (5.2.2) 一直持续到完成 包含调用的完整表达式

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


3
投票

在第 12.2 节“临时对象”第 3 条中,ANSI/ISO C 标准规定:“...临时对象在评估(词法上)包含它们创建点的完整表达式的最后一步被销毁。”

这与序列点的概念密切相关。当到达序列点时,表达式的所有副作用都保证已经发生。

© www.soinside.com 2019 - 2024. All rights reserved.