【问题标题】:Argument evaluation order between curly braces and parentheses花括号和圆括号之间的参数求值顺序
【发布时间】:2019-12-17 22:09:11
【问题描述】:
#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 将在两种情况下打印相同的订单。

我在标准中找不到任何关于它的内容,是在标准中还是由编译器决定它评估输入参数的命令?

【问题讨论】:

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


    【解决方案1】:

    只保证braced-init-list的顺序,[dcl.init.list]/4:

    (强调我的)

    在花括号初始化列表的初始化列表中,初始化子句,包括任何由包扩展 ([temp.variadic]) 产生的子句,按照它们出现的顺序进行评估强>。也就是说,与给定初始化子句相关联的每个值计算和副作用在初始化器列表的逗号分隔列表中与任何初始化子句相关联的每个值计算和副作用之前进行排序。 [ 注意:无论初始化的语义如何,这种求值顺序都成立;例如,它适用于初始化器列表的元素被解释为构造函数调用的参数时,即使调用的参数通常没有顺序限制。 — 结束注释]

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

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

    【讨论】:

    • 请注意,在 C++17 之前,不同参数的(子表达式)可以交错,这样f(std::unique_ptr&lt;T&gt;(new T),std::unique_ptr&lt;T&gt;(new T)) 可能会泄漏一个对象,如果另一个的建设失败了。
    【解决方案2】:

    Clang 似乎评估了此声明中的参数

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

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

    参数的评估顺序未指定。

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

    【讨论】:

    • @NicolBolas 可以说是排序的。:)
    • 您的答案中的代码是否应该带有括号而不是大括号?
    • @L.F.有人在不让我知道的情况下更改了代码。
    猜你喜欢
    • 2014-11-26
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    相关资源
    最近更新 更多