c++ - GCC 语句表达式中的执行顺序
问题描述
我发现两个相似的语句之间有不同的执行顺序(唯一的区别是下面的语句有一个附加的;
)。析构函数的顺序不同。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>();;});
}
输出:
S(1)
S(2)
~S(1)
~S(2)
-----------------------------------
S(3)
S(4)
~S(4)
~S(3)
解决方案
这不是标准的 C++。这是一个称为语句表达式的 GCC 扩展。括号中的复合语句可以出现在允许表达式的地方。如果大括号括起来的块中的最后一条语句是一个表达式语句,那么这个表达式的值也是整个语句表达式的值;否则,语句表达式是类型void
并且没有值。
你的第一个例子大致相当于
([](){ return S<1>(), S<2>(); })();
(这是一个创建然后立即调用的 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
但是 (1)/(2) 对被省略了,留下了您在示例中观察到的序列。
在第二个示例中,大括号中的最后一条语句不是表达式,因此整个内容也没有值。大致相当于
([](){ S<3>(), S<4>(); return; })();
两个临时对象都是在 lambda 中创建和销毁的,并且适用通常的规则 - 临时对象以与构造相反的顺序被销毁。
推荐阅读
- unity3d - 共享 Play 商店链接“将添加预览”问题
- python-3.x - OCR前包裹投递单的图像预处理问题
- python - 从 BigQuery 获取数据需要很长时间
- c++ - 当 getline 直到换行才读取时会发生什么?
- apache-kafka - Kafka Rest Api 不适用于同一组中的两个或多个消费者
- django - 由于TTFB时间长,Django页面加载时间太慢
- visual-studio-code - 如果子目录在 Visual Studio Code 中为空,如何禁用子目录的内联?
- java - 从对象中获取类名
- google-apps-script - 创建一个数组,在 Google 表单的 setchoices 中将答案选项分配为 true 或 false
- javascript - 使用 Jquery 获取实际的表列