2016-05-16 86 views
1

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

以下是与标准相关的引用,与初始化列表有关吗?

§8.5.4.4:在一个支撑-INIT-列表的初始化列表中, 初始化子句,包括任何从包膨胀导致 (§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 
+4

您的代码不包含任何初始值设定项列表。 –

+3

在C++中未指定函数参数的评估顺序。 – 101010

+0

http://stackoverflow.com/questions/621542/compilers-and-argument-order-of-evaluation-in-c –

回答

0

在我看来,这报价是相关的(编译器看到一个初始化列表):

8.5/14, 16:

发生的初始化形式为

T x = a;

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

初始值设定项的语义如下[...]:如果初始值设定项是一个braced-init-list,则该对象被初始化(8.5.4)。

(在std::initializer_list as function argumentFolds (ish) In C++11更多细节)

而且任何{} -list应测序(标准使用这个其实是一个很强烈的措辞。另请参见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)。

+0

考虑编辑后 – Adib

+0

我试过了在任何情况下结果是相同的problrm不添加--std = c + + 11 – Adib

+0

@ user5905343不幸的是gcc v4.8.4缺少在https://gcc.godbolt.org但考虑到上述测试它似乎是一个错误。 – manlio

2

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

[C++14: 5.17/9]:支撑-INIT列表可以对

  • 分配的右手侧显示为一个标量,在这种情况下,初始化列表应至多单个元件具有。 x={v}的含义,其中T是表达式x的标量类型,是x=T{v}的标量类型。 x={}的含义是x=T{}
  • 对类类型的对象的赋值,在这种情况下,初始化程序列表作为参数传递给由重载决策选择的赋值运算符函数(13.5.3,13.3)。
+0

也许我错了,但* braced-init-list *可能出现在许多其他的上下文中。 * for-range-initializer *('for(for-range-declaration:braced-init-list)statement,§6.5.4),* jump-statements *('return braced-init-list;',§6.6 ),... – manlio

+0

@manlio:呃,好吧,我确实试图找到_this_案例中没有_braced-init-list_的证据(这将是一个更好的答案),但得出的结论是我必须引用太多。 –

+0

还考虑[std :: initializer_list作为函数参数](http://stackoverflow.com/q/2357452/3235496),特别是[此答案](http://stackoverflow.com/a/2357688/3235496),参数传递应该和'='初始化器具有相同的含义(都是复制初始化)。所以不是这个副本初始化(对象*列表初始化*通过* braced-init-list *)? – manlio