C++ g++ -Wreorder 有什么意义?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1828037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:19:02  来源:igfitidea点击:

What's the point of g++ -Wreorder?

c++g++compiler-warnings

提问by Peeter Joot

The g++ -Wall option includes -Wreorder. What this option does is described below. It is not obvious to me why somebody would care (especially enough to turn this on by default in -Wall).

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.

回答by int3

Consider:

考虑:

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

Now iis initialized to some unknown value, not zero.

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

Alternatively, the initialization of imay have some side effects for which the order is important. E.g.

或者, 的初始化i可能会产生一些顺序很重要的副作用。例如

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

回答by Steve Jessop

The problem is that somebody might see the list of member initialisers in the constructor, and think that they're executed in that order (j first, then i). They are not, they are executed in the order the members are defined in the class.

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

Suppose you wrote A(): j(0), i(j) {}. Somebody might read that, and think that i ends up with the value 0. It doesn't, because you initialised it with j, which contains junk because it has not itself been initialised.

假设你写了A(): j(0), i(j) {}. 有人可能会读到它,并认为 i 以值 0 结束。它没有,因为你用 j 初始化它,它包含垃圾,因为它本身没有被初始化。

The warning reminds you to write A(): i(j), j(0) {}, which hopefully looks a lot more fishy.

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

回答by gkb0986

Other answers have provided some good examples that justify the option for a warning. I thought I'd provide some historical context. The creator of C++, Bjarne Stroustrup, explains in his book The C++ programming language(3rd edition, Page 259):

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

The members' constructors are called before the body of the containing class' own constructor is executed. The constructors are called in the order in which they are declared in the class rather than the order in which they appear in the initializer list. To avoid confusion, it is best to specify the initializers in declaration order. The member destructors are called in the reverse order of construction.

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

回答by Pavel Minaev

This can bite you if your initializers have side effects. Consider:

如果您的初始值设定项有副作用,这可能会咬您。考虑:

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

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

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

The above will print "bar" then "foo", even though intuitively one would assume that order is as written in the initializer list.

上面将打印“bar”然后是“foo”,尽管直觉上人们会假设顺序是写在初始化列表中的。

Alternatively, if xand yare of some user-defined type with a constructor, that constructor may also have side effects, with the same non-obvious result.

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

It can also manifest itself when initializer for one member references another member.

当一个成员的初始化程序引用另一个成员时,它也可以表现出来。

回答by jalf

The warning exists because if you just read the constructor, it looks like jis getting initialized before i. This becomes a problem if one is used to initialize the other, as in

警告存在是因为如果您只是阅读构造函数,它看起来像是ji. 如果一个用于初始化另一个,这将成为一个问题,如

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

When you just look at the constructor, this lookssafe. But in reality, jhas not yet been initialized at the point where it is used to initialize i, and so the code won't work as expected. Hence the warning.

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