G + +-Wreorder 的意义是什么?

G + +-Wall 选项包括-Wreorder。此选项的作用如下所述。我不明白为什么有人会关心这个(特别是足以在-Wall 中默认打开这个)。

-Wreorder (C++ only)
Warn when the order of member initializers given in the code does not
match the order in which they must be executed.  For instance:


struct A {
int i;
int j;
A(): j (0), i (1) { }
};


The compiler will rearrange the member initializers for i and j to
match the declaration order of the members, emit-ting a warning to that
effect.  This warning is enabled by -Wall.
62400 次浏览

考虑一下:

struct A {
int i;
int j;
A() : j(0), i(j) { }
};

现在,i被初始化为某个未知值,而不是零。

另外,i的初始化可能会产生一些副作用,这些副作用对顺序很重要。

A(int n) : j(n++), i(n++) { }

如果你的初始化程序有副作用的话,这可能会伤害到你。考虑一下:

int foo() {
puts("foo");
return 1;
}


int bar() {
puts("bar");
return 2;
}


struct baz {
int x, y;
baz() : y(foo()), x(bar()) {}
};

以上将打印“酒吧”,然后“ foo”,即使直观地假设顺序是写在初始化程序列表。

或者,如果 xy是某种用户定义类型的构造函数,那么该构造函数也可能有副作用,具有相同的不明显的结果。

当一个成员的初始值设定项引用另一个成员时,它也可以显示自己。

问题是,有人可能在构造函数中看到成员初始化程序列表,并认为它们是按照这个顺序执行的(j 先,然后 i)。它们不是,它们是按照类中定义成员的顺序执行的。

假设您编写了 A(): j(0), i(j) {}。有人可能会读到这个,然后认为我最终得到的值是0。它没有,因为你用 j 初始化了它,其中包含垃圾,因为它本身没有被初始化。

这个警告提醒您编写 A(): i(j), j(0) {},希望它看起来更加可疑。

这个警告之所以存在,是因为如果您只是读取构造函数,那么看起来 j是在 i之前被初始化的。如果使用其中一个来初始化另一个,则会出现问题,如

struct A {
int i;
int j;
A(): j (0), i (this->j) { }
};

当你看构造函数的时候,这个 看起来保险箱。但实际上,j还没有被初始化到用来初始化 i的位置,因此代码不会像预期的那样工作。所以我才警告你。

其他答案提供了一些很好的例子,证明了警告选项的合理性。我想我可以提供一些历史背景。C + + 的创造者,比雅尼·斯特劳斯特鲁普,在他的书中解释说:

在执行包含类自己的构造函数体之前调用成员的构造函数。构造函数的调用顺序是它们在类中声明的顺序,而不是它们在初始化器列表中出现的顺序。为了避免混淆,最好按声明顺序指定初始值设定项。成员析构函数的调用顺序与构造顺序相反。