花括号和括号之间的参数评估顺序

时间:2019-08-10 13:01:39

标签: c++ c++11 constructor language-lawyer c++17

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

uint32_t func() { return rand() % 10; }

struct A {
  uint32_t _x, _y, _z;
  A(uint32_t x, uint32_t y, uint32_t z) : _x(x), _y(y), _z(z) {}
};

int main() {
  A a{func(), func(), func()};
  //A a(func(), func(), func());

  printf("%d %d %d\n", a._x, a._y, a._z);
  return 0;
}
当使用大括号或括号时,

GCC 9.1MSVC 19.22.27905都将打印不同的顺序。 Clang 8.0.0将为两种情况打印相同的顺序。

我在标准中找不到任何东西,是在标准中找到还是由编译器命令它评估输入参数?

2 个答案:

答案 0 :(得分:9)

仅对括号初始列表[dcl.init.list]/4中的顺序有保证:

(重点是我的)

  

在括号初始化列表的初始化列表中,初始化子句(包括由于包扩展([temp.variadic])导致的所有子句,按照它们出现的顺序进行评估。也就是说,在给定的初始化列表中以逗号分隔的列表中,与给定的初始化子条款相关的每个值计算和副作用在与跟随其后的任何初始化子条款相关的每个值计算和副作用之前进行排序。 [注意:无论初始化的语义如何,此评估顺序均成立;例如,当通常将初始化器列表的元素解释为构造函数调用的参数时,即使在调用的参数上通常没有顺序约束,它也适用。 —结尾说明]

另一方面,order of evaluation of arguments in a function callunspecified

  

未指定的行为-程序的行为在不同的实现之间有所不同,不需要一致的实现来记录每种行为的效果。例如,order of evaluation,是否相同的string literals是否不同,数组分配开销的数量等。每个未指定的行为都会导致一组有效结果中的一个。

答案 1 :(得分:1)

似乎Clang在此声明中计算参数

A a( func(), func(), func() );

从左到右。而其他编译器按从右到左的顺序评估它们。

未指定参数的求值顺序。

对于花括号,则严格从左到右确定评估,并对每个表达式的评估进行排序。