Answers:
考虑:
struct A {
int i;
int j;
A() : j(0), i(j) { }
};
现在i
已初始化为某个未知值,而不是零。
或者,的初始化i
可能会带来一些副作用,对于这些副作用而言,顺序很重要。例如
A(int n) : j(n++), i(n++) { }
i
初始化为1
)。在这里,i
被初始化为j
,实际上表明了一个问题。
其他答案提供了一些很好的例子,证明了警告选项的合理性。我以为我会提供一些历史背景。C ++的创建者Bjarne Stroustrup在他的《 C ++编程语言》(第3版,第259页)中作了解释:
在执行包含类自己的构造函数的主体之前,将调用成员的构造函数。构造函数的调用顺序是在类中声明的顺序,而不是它们在初始化列表中出现的顺序。为避免混淆,最好按声明顺序指定初始化程序。成员析构函数以相反的构造顺序调用。
如果初始化程序有副作用,这可能会咬人。考虑:
int foo() {
puts("foo");
return 1;
}
int bar() {
puts("bar");
return 2;
}
struct baz {
int x, y;
baz() : y(foo()), x(bar()) {}
};
上面的代码将先打印“ bar”,然后打印“ foo”,即使直觉上会假定顺序与初始化列表中的相同。
或者,如果x
和y
具有某些用户定义类型且带有构造函数,则该构造函数也可能具有副作用,并且具有相同的非显而易见的结果。
当一个成员的初始值设定项引用另一成员时,它也可以表现出来。
-Werror=reorder