代码之家  ›  专栏  ›  技术社区  ›  Peeter Joot

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

  •  128
  • Peeter Joot  · 技术社区  · 15 年前

    g++-wall选项包括-wreorder。此选项的作用如下所述。我不明白为什么有人会在意(尤其是在默认情况下,在墙上打开它)。

    -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.
    
    5 回复  |  直到 12 年前
        1
  •  224
  •   int3    15 年前

    考虑:

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

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

    或者,初始化 可能会有一些副作用,这对顺序很重要。例如。

    A(int n) : j(n++), i(n++) { }
    
        2
  •  35
  •   Steve Jessop    15 年前

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

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

    警告提醒你写 A(): i(j), j(0) {} 希望看起来更有鱼味。

        3
  •  14
  •   gkb0986    12 年前

    其他答案也提供了一些很好的例子来证明警告的选择是正确的。我想我会提供一些历史背景。C++的创造者,Bjarne Stroustrup,在他的书中解释 The C++ programming language (第3版,第259页):

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

        4
  •  9
  •   Pavel Minaev    15 年前

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

    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 是一些带有构造函数的用户定义类型,该构造函数也可能有副作用,具有相同的不明显结果。

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

        5
  •  6
  •   Stack Overflow is garbage    15 年前

    警告存在,因为如果您刚刚读取构造函数,它看起来像 j 之前正在初始化 i . 如果使用其中一个初始化另一个,这将成为一个问题,如

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

    当您只查看构造函数时, 安全。但实际上, J 尚未在用于初始化的点进行初始化 ,因此代码无法按预期工作。因此发出了警告。