标准C++ 11是否保证传递给函数的临时对象在函数结束后会被销毁?

Ale*_*lex 6 c++ standards sequence-points lazy-sequences c++11

众所周知,标准C++ 11保证传递给函数的临时对象将在函数调用之前创建:标准C++ 11是否保证在函数调用之前创建传递给函数的临时对象?

但是,标准C++ 11是否保证传递给函数的临时对象在函数结束后(之前没有)被销毁?

工作草案,编程语言标准C++ 2016-07-12:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf

§12.2临时对象

§12.2/ 5

有三种情况下,临时表在与完整表达结束时不同的点被摧毁.第一个上下文是调用默认构造函数来初始化没有相应初始值设定项的数组元素(8.6).第二个上下文是在复制整个数组时调用复制构造函数来复制数组的元素(5.1.5,12.8).在任何一种情况下,如果构造函数具有一个或多个默认参数,则在构造下一个数组元素(如果有)之前,对默认参数中创建的每个临时的销毁进行排序.第三个上下文是引用绑定到临时的.

也:

§1.9/ 10

全表达为不是另一种表达的子表达式的表达式.[注意:在某些情况下,例如未评估的操作数,语法子表达式被视为完整表达式(第5条). - 结束注释]如果定义语言构造以产生函数的隐式调用,则语言构造的使用被认为是用于该定义目的的表达式.在临时对象以外的对象的生命周期结束时生成的析构函数的调用是隐式的完整表达式.应用于表达式结果的转换以满足表达式出现的语言构造的要求也被认为是完整表达式的一部分.

这是否意味着标准C++ 11保证传递给函数的临时对象不会在函数结束之前被破坏 - 并且恰好在完整表达式的末尾?

http://ideone.com/GbEPaK

#include <iostream>
using namespace std;

struct T { 
    T() { std::cout << "T created \n"; }
    int val = 0;
    ~T() { std::cout << "T destroyed \n"; }
};

void function(T t_obj, T &&t, int &&val) {
    std::cout << "func-start \n";
    std::cout << t_obj.val << ", " << t.val << ", " << val << std::endl;
    std::cout << "func-end \n";
}

int main() {

    function(T(), T(), T().val);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

T created 
T created 
T created 
func-start 
0, 0, 0
func-end 
T destroyed 
T destroyed 
T destroyed 
Run Code Online (Sandbox Code Playgroud)

我们可以说T destroyed 永远都会在之后func-end吗?

还有这个:

function(T(), T(), T().val);
Run Code Online (Sandbox Code Playgroud)

始终等于以下内容:

{
    T tmp1; T tmp2; T tmp3;
    function(tmp1, tmp2, tmp3.val);
}
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 7

好吧,你已经引用了所有文字告诉我们临时的生命周期在完整表达结束时结束.所以,是的," T destroyed"将永远是最后的.

如果破坏没有可观察到的副作用那么,按照as-if规则,它实际上可能在之后的任何时间发生......但这没有实际意义,因为它是不可观察的.

但是,您提供的最后两个片段通常不等同,因为您以前所未有的方式修复了构造/初始化的顺序.函数参数具有未指定的评估顺序.但是,对于这个特殊情况T,差异是不可观察的.

  • 只是一个小修复:你可能想说"永远都会来****". (2认同)