初始化列表中元素的评估顺序
Evaluation order of elements in an initializer list
为什么先调用函数 g()
?我将 g()
定义为初始化列表中的第二个元素。
标准中与初始值设定项列表相关的以下引述是否相关?
§8.5.4.4: Within the initializer-list of a braced-init-list, the
initializer-clauses, including any that result from pack expansions
(§14.5.3), are evaluated in the order in which they appear.
#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
在我看来引用是相关的(编译器看到一个初始化列表):
8.5/14,16:
The initialization that occurs in the form
T x = a;
as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization.
.
.
The semantics of initializers are as follows[...]: If the initializer is a braced-init-list, the object is list-initialized (8.5.4).
(std::initializer_list as function argument and Folds (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 仍会编译代码(带有警告,例如参见 [=18=])。
这不是 braced-init-list,因此该规则不适用。
[C++14: 5.17/9]:
A braced-init-list may appear on the right-hand side of
- an assignment to a scalar, in which case the initializer list shall have at most a single element. The meaning of
x={v}
, where T
is the scalar type of the expression x
, is that of x=T{v}
. The meaning of x={}
is x=T{}
.
- an assignment to an object of class type, in which case the initializer list is passed as the argument to the assignment operator function selected by overload resolution (13.5.3, 13.3).
为什么先调用函数 g()
?我将 g()
定义为初始化列表中的第二个元素。
标准中与初始值设定项列表相关的以下引述是否相关?
§8.5.4.4: Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (§14.5.3), are evaluated in the order in which they appear.
#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
在我看来引用是相关的(编译器看到一个初始化列表):
8.5/14,16:
The initialization that occurs in the form
T x = a;
as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization.
.
.
The semantics of initializers are as follows[...]: If the initializer is a braced-init-list, the object is list-initialized (8.5.4).
(std::initializer_list as function argument and Folds (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 仍会编译代码(带有警告,例如参见 [=18=])。
这不是 braced-init-list,因此该规则不适用。
[C++14: 5.17/9]:
A braced-init-list may appear on the right-hand side of
- an assignment to a scalar, in which case the initializer list shall have at most a single element. The meaning of
x={v}
, whereT
is the scalar type of the expressionx
, is that ofx=T{v}
. The meaning ofx={}
isx=T{}
.- an assignment to an object of class type, in which case the initializer list is passed as the argument to the assignment operator function selected by overload resolution (13.5.3, 13.3).