初始化列表中元素的评估顺序

时间:2016-05-16 13:13:25

标签: c++ gcc operator-precedence

为什么函数g()首先被调用?我将g()定义为初始化列表中的第二个元素。

与初始化列表相关的标准中的以下引用是否相关?

  

§8.5.4.4:在braced-init-list的initializer-list中,   initializer-clause,包括包扩展产生的任何条款   (§14.5.3),按照它们出现的顺序进行评估。

#include <iostream>
#include <vector>

int f() { std::cout << "f"; return 0;}
int g() { std::cout << "g"; return 0;}

void h(std::vector<int> v) {}

int main() {

   h({f(), g()});
}

输出:

gf

2 个答案:

答案 0 :(得分:2)

这不是 braced-init-list ,因此该规则不适用。

  

[C++14: 5.17/9]: braced-init-list 可能会出现在

的右侧      
      
  • 对标量的赋值,在这种情况下,初始化列表最多只能包含一个元素。 x={v}的含义T是表达式x的标量类型,是x=T{v}的含义。 x={}的含义为x=T{}
  •   
  • 对类类型对象的赋值,在这种情况下,初始化列表作为参数传递给由重载决策(13.5.3,13.3)选择的赋值运算符函数。
  •   

答案 1 :(得分:0)

在我看来,引用是相关的(编译器看到初始化列表):

  

8.5 / 14,16:

     

形式出现的初始化      

T x = a;

     

以及参数传递,函数返回,抛出异常(15.1),处理异常(15.3)和聚合成员初始化(8.5.1)称为复制初始化。 / p>      

     

     

初始化器的语义如下[...]:如果初始化器是braced-init-list,则对象是列表初始化的(8.5.4)。

std::initializer_list as function argumentFolds (ish) In C++11中的详细信息)

此外,任何{} - 列表都应该排序(标准使用了一个非常强烈的关于这一事实的措辞。另见http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1030)。

所以它是probably a GCC bug(在gcc v4.9.0之后修复)。

确实,尝试各种GCC版本,我得到:

GCC      with --std=c++11   without (--std=c++98)
4.7.3        fg                    gf  <-
4.8.1        fg                    gf  <-
4.8.2        fg                    gf  <-
4.9.0        fg                    gf  <-
4.9.2        fg                    fg
5.1.0        fg                    fg
5.2.0        fg                    fg
6.1.0        fg                    fg

扩展初始化列表仅适用于C ++ 11,但GCC仍会编译代码(带有警告,例如,请参阅gcc -Wall -Wextra vs gcc -Wall -Wextra -std=c++11)。