C++中花括号或等号初始化器与初始化列表之间的求值顺序是什么?

7

我有这个结构体:

struct
AAA
{
    AAA() : bbb(2)
    {
        // ccc ???
    }

    int bbb = 1;
    int ccc = bbb;
};

据我所知, 如果有一个初始化列表:bbb(2),那么表达式bbb = 1将会被忽略。然后,对于ccc最终会变成什么,我感到很模糊。

初始化列表花括号或等号初始化器中哪一个会先被评估?它们之间的规则是什么?


1
为什么不检查一下呢? - klm123
4
我认为具体的实现并不能保证实际的规则。 - eonil
@KateGregory 嗯,我知道你,所以我敢暗示你错了,但这怎么与§12.6.2.9相结合? :) - Joachim Isaksson
1
在VS2013的预发布版本中,我会因为两种情况得到警告。然而,我刚刚检查了一下正式版本,似乎只有“:()”这种情况才会发生,非静态成员初始化不会发生。测试是无可替代的。 - Kate Gregory
2个回答

12

C++11草案 §12.6.2.9 规定:

如果一个非静态数据成员既有花括号或等号初始化式又有成员初始值设定项,那么执行由成员初始值设定项指定的初始化,并忽略非静态数据成员的花括号或等号初始化式。

[ 例如:给定

struct A {
  int i = /∗ some integer expression with side effects ∗/ ; 
  A(int arg) : i(arg) { }
  // ...
};

构造函数 A(int) 将简单地将 i 初始化为 arg 的值,并且 i 中花括号或等号初始化器中的副作用不会发生。 —— 结束示例 ]

由于初始化是按照声明顺序进行的(§12.6.2.10),加上这个规则,bbbccc 的值都将是2。


我认为紧随其后的段落更相关。p9实际上并没有说明bbb和ccc之间初始化的顺序,它只是说bbb不会被初始化两次。 - user743382
@hvd 引用问题,“初始化列表和花括号或等号初始化器哪一个会先被评估?”,虽然我认为这两个规则都很重要。 - Joachim Isaksson
@JoachimIsaksson 哦,我明白你是怎么读这个问题的。我以为 OP 的意思是初始化列表 (bbb) 或大括号或等于初始化器 (ccc),而不是初始化列表 (bbb) 或大括号或等于初始化器 (bbb, ccc)。 - user743382
当忽略bbb=1时,顺序是显然的,先执行bbb=2,然后执行ccc=bbb,所以ccc=2。我认为根据第9段文字,执行顺序没有歧义。 - masoud
1
@MM。p9并没有说“然后”,是p10说的。如果你颠倒bbb和ccc的声明,首先运行ccc=bbb(未定义的行为,在实践中将ccc设置为不可预测的值),然后才是bbb=2。 - user743382

11

规则一直是字段的初始化顺序与声明顺序相同,C++11也没有改变这一点。这意味着bbb的初始化程序首先运行,然后是ccc的初始化程序。无论初始值设定项是在字段上指定还是作为构造函数的一部分,都不重要。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接