168

g++ -Wall オプションには -Wreorder が含まれます。このオプションが何をするかを以下に説明します。なぜ誰かが気にするのかは、私には明らかではありません (特に、-Wall でデフォルトでこれを有効にするのに十分です)。

-Wreorder (C++ のみ)
  コードで指定されたメンバー初期化子の順序が正しくない場合に警告します
  実行する必要がある順序に一致させます。例えば:

    構造体 A {
      int i;
      int j;
      A(): j (0), i (1) { }
    };

  コンパイラは、i および j のメンバー初期化子を次のように再配置します。
  メンバーの宣言順序を一致させ、それに対して警告を発する
  効果。この警告は -Wall によって有効になります。
4

5 に答える 5

280

検討:

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

iゼロではなく、不明な値に初期化されるようになりました。

あるいは、 の初期化にiは、順序が重要な副作用がある場合があります。例えば

A(int n) : j(n++), i(n++) { }
于 2009-12-01T18:40:30.193 に答える
49

問題は、誰かがコンストラクター内のメンバー初期化子のリストを見て、それらがその順序で実行されていると考える可能性があることです (最初に j、次に i)。そうではなく、メンバーがクラスで定義されている順序で実行されます。

あなたが書いたとしますA(): j(0), i(j) {}。誰かがそれを読んで、i が値 0 で終わると考えるかもしれません。それ自体が初期化されていないため、ジャンクを含む j で初期化したため、そうではありません。

A(): i(j), j(0) {}この警告は、より怪しげに見えることを願って、を書くように促します。

于 2009-12-01T18:42:10.220 に答える
21

他の回答は、警告のオプションを正当化するいくつかの良い例を提供しています。歴史的な文脈を提供しようと思いました。C++ の作成者である Bjarne Stroustrup は、著書The C++ programming language (第 3 版、259 ページ) で次のように説明しています。

メンバーのコンストラクターは、それを含むクラスの独自のコンストラクターの本体が実行される前に呼び出されます。コンストラクターは、初期化子リストに表示される順序ではなく、クラスで宣言された順序で呼び出されます。混乱を避けるために、イニシャライザは宣言順に指定することをお勧めします。メンバ デストラクタは、構築の逆の順序で呼び出されます。

于 2013-02-16T12:44:52.140 に答える
13

初期化子に副作用がある場合、これはあなたを苦しめる可能性があります。検討:

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がコンストラクターを持つユーザー定義型である場合、そのコンストラクターにも副作用があり、同じ明らかでない結果が生じる可能性があります。

また、あるメンバーの初期化子が別のメンバーを参照するときにも現れます。

于 2009-12-01T18:40:59.733 に答える
8

jコンストラクターを読み取っただけでは、 が の前に初期化されているように見えるため、警告が存在しますi。次のように、一方が他方を初期化するために使用される場合、これは問題になります。

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

コンストラクタだけを見ると、これは安全に見えます。しかし実際にjは、 は初期化に使用される時点でまだ初期化されていないiため、コードは期待どおりに動作しません。したがって、警告。

于 2009-12-01T18:42:15.330 に答える