g ++ -Wreorder有什么意义?


150

g ++ -Wall选项包括-Wreorder。下面介绍此选项的作用。对我来说,为什么有人会关心(尤其是默认在-Wall中将其打开)并不明显。

-Wreorder(仅C ++)
  当代码中给定的成员初始化程序的顺序不正确时发出警告
  匹配必须执行的顺序。例如:

    结构A {
      我
      int j;
      A():j(0),i(1){}
    };

  编译器将重新排列i和j的成员初始化器。
  匹配成员的声明顺序,对此发出警告
  影响。该警告由-Wall启用。

2
这里有一些很好的答案,但如果有人感兴趣的话,可以做一个简短的介绍:g ++有一个标记将其视为一个完整的错误:-Werror=reorder
Max Barraclough

Answers:


257

考虑:

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

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

或者,的初始化i可能会带来一些副作用,对于这些副作用而言,顺序很重要。例如

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

80
这确实是文档中的示例。
本S

3
谢谢。由于我们的大多数类型都是带有简单初始化程序的POD类型,这对我来说是没有发生的。您的示例比g ++手册示例要好得多。
Peeter Joot 09年

5
@Mike这是因为您的编译器(gcc)将未初始化的变量初始化为0,但这不是您应该依赖的东西;i是0只是未初始化变量的未知值的一个副作用是0
ethanwu10

2
@Yakk的顺序是手册页->这样的答案。这是2007年手册页的存档,其中明确列出了此示例。Ben S的强烈评论是一个热闹的例子,有人暗示某物存在,甚至没有检查它是否已经存在。web.archive.org/web/20070712184121/http://linux.die.net/man/1/…–
KymikoLoco

3
@KymikoLoco那是完全错误的。手册页中的示例是来自OP的示例(其中i初始化为1)。在这里,i被初始化为j,实际上表明了一个问题。
jazzpi

42

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

假设您写了A(): j(0), i(j) {}。有人可能会读到它,并认为我的值最终为0。它不是,因为您用j对其进行了初始化,其中j包含垃圾,因为它本身尚未初始化。

警告提示您写A(): i(j), j(0) {},希望看起来更脏。


看起来确实/闻起来很腥!:)绝对会发出代码气味:)感谢您的明确说明。:)
威尔

1
“ ...提醒您编写A():i(j),j(0){} ...”我建议它提醒您在这种特殊情况下对类成员重新排序。
2.718

18

其他答案提供了一些很好的例子,证明了警告选项的合理性。我以为我会提供一些历史背景。C ++的创建者Bjarne Stroustrup在他的《 C ++编程语言》(第3版,第259页)中作了解释:

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


10

如果初始化程序有副作用,这可能会咬人。考虑:

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

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

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

上面的代码将先打印“ bar”,然后打印“ foo”,即使直觉上会假定顺序与初始化列表中的相同。

或者,如果xy具有某些用户定义类型且带有构造函数,则该构造函数也可能具有副作用,并且具有相同的非显而易见的结果。

当一个成员的初始值设定项引用另一成员时,它也可以表现出来。


7

该警告的存在是因为,如果您只是阅读构造函数,则它看起来像是j在之前被初始化的i。如果一个用来初始化另一个,这将成为一个问题,例如

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

当您只看构造函数时,这看起来很安全。但实际上,j尚未在用于初始化的位置进行初始化i,因此代码无法按预期工作。因此,警告。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.