成员初始化中表达式的评估是否相互排序?

时间:2014-03-11 15:09:37

标签: c++ constructor member language-lawyer

具体来说,我说:

struct X { X(int i) { cout << i; } };
int f() { cout << 'f'; return 0; }
int g() { cout << 'g'; return 1; }

struct Z {
    Z() : a(f()), b(g()) {}
    X a, b;
};

int main() { Z z; cout << '\n'; }

我知道成员的构造函数保证按照struct中定义的顺序调用,因此0将在1之前打印。 但是如何评价他们的论点呢?是否保证:

f0g1

?或者,或许,

fg01

gf01

也是有效的输出?

赞赏参考标准。

2 个答案:

答案 0 :(得分:5)

C++11 draft standard中,每个成员初始化程序都是一个完整表达式,因此所有副作用必须在评估下一个之前生效。

部分12.6.2 初始化基础和成员 7 说:

  

[...]每个mem-initializer执行的初始化构成一个完整表达式。任何   mem-initializer中的表达式被评估为执行初始化的完整表达式的一部分。[...]

和部分1.9 计划执行 14 说:

  

在每个值计算和与要评估的下一个完整表达式相关的副作用之前,对与全表达式相关的每个值计算和副作用进行排序。

12.6.2部分的相关语法如下:

ctor-initializer:
   : mem-initializer-list
mem-initializer-list:
   mem-initializer ...opt
   mem-initializer , mem-initializer-list ...opt
[...]

C ++ 11 每个 mem-initializer 作为完整表达式的相同措辞不存在,至少不是最早的可用草案标准{{ 3}}。但据我所知,我在1804中使用的逻辑同样适用于这种情况,因此我们也应该期待 C ++ 11 之前的相同行为。

答案 1 :(得分:2)

根据C ++标准

  

每个mem-initializer执行的初始化构成一个   充分表达。 mem-initializer中的任何表达式都被评估为   执行初始化的全表达式的一部分

首先,将执行完整表达式a(f()),然后执行完整表达式b(g())。

结果输出必须是

f0g1