практическое - c++ struct default initialization



В чем смысл g++-Wreorder? (4)

Опция 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.

Answer #1

Другие ответы предоставили несколько хороших примеров, которые оправдывают вариант предупреждения. Я думал, что предоставил бы какой-то исторический контекст. Создатель C ++, Bjarne Stroustrup, объясняет в своей книге « Язык программирования C ++» (3-е издание, стр. 259):

Конструкторы членов вызываются до того, как будет выполнен собственный конструктор содержащего класса. Конструкторы вызываются в том порядке, в котором они объявлены в классе, а не в порядке, в котором они отображаются в списке инициализаторов. Чтобы избежать путаницы, лучше указать инициализаторы в порядке объявления. Деструкторы-члены вызываются в обратном порядке построения.


Answer #2

Предупреждение существует, потому что, если вы просто прочитали конструктор, похоже, что j инициализируется до i . Это становится проблемой, если кто-то используется для инициализации другого, как в

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

Когда вы просто смотрите на конструктор, это выглядит безопасным. Но на самом деле j еще не был инициализирован в точке, где он используется для инициализации i , и поэтому код не будет работать должным образом. Отсюда предупреждение.


Answer #3

Рассматривать:

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

Теперь i инициализируется некоторым неизвестным значением, а не нулем.

Альтернативно, инициализация i может иметь некоторые побочные эффекты, для которых порядок важен. Например

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

Answer #4

Это может укусить вас, если ваши инициализаторы имеют побочные эффекты. Рассматривать:

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 имеют определенный пользовательский тип с конструктором, этот конструктор может также иметь побочные эффекты с тем же неочевидным результатом.

Он также может проявляться, когда инициализатор для одного члена ссылается на другой член.





compiler-warnings