edd*_*kuo 2 c++ gcc gcc-statement-expression
我发现两个相似的语句之间有不同的执行顺序(唯一的区别是下面有一个额外的;)。析构函数顺序不同。C++ 是否有相应的规范,或者它只是一种未指定的行为?
环境:GCC10
#include <iostream>
template <int num>
struct S {
S() {std::cout << "S(" << num << ")\n"; }
~S() {std::cout << "~S(" << num << ")\n"; }
};
int main() {
({S<1>(), S<2>();});
std::cout << "-----------------------------------\n";
({S<3>(), S<4>();;});
}
Run Code Online (Sandbox Code Playgroud)
输出:
S(1)
S(2)
~S(1)
~S(2)
-----------------------------------
S(3)
S(4)
~S(4)
~S(3)
Run Code Online (Sandbox Code Playgroud)
这不是标准的 C++。这是称为语句表达式的 GCC 扩展。括号中的复合语句可以出现在允许使用表达式的地方。如果大括号括起来的块中的最后一条语句是表达式语句,则该表达式的值也是整个语句表达式的值;否则,语句表达式为类型void且没有值。
你的第一个例子大致相当于
([](){ return S<1>(), S<2>(); })();
Run Code Online (Sandbox Code Playgroud)
(这是一个创建然后立即调用的 lambda)。有一个逗号表达式可以创建S<1>和S<2>临时。S<1>被销毁,S<2>从技术上讲,被复制到返回值 - 但该副本被省略。如果不是这个复制省略,你会看到
S<1>()
S<2>()
S<2>(S<2>&&) // (1) move constructor
~S<2>() // (2) the original temporary is destroyed
~S<1>()
~S<2>() // the copy is destroyed outside of the lambda
Run Code Online (Sandbox Code Playgroud)
但是 (1)/(2) 对被省略,留下您在示例中观察到的序列。
在第二个示例中,大括号内的最后一条语句不是表达式,因此整个内容也没有值。它大致相当于
([](){ S<3>(), S<4>(); return; })();
Run Code Online (Sandbox Code Playgroud)
两个临时对象都在 lambda 中创建和销毁,通常的规则适用 - 临时对象以与构造相反的顺序销毁。