Порядок оценки списка инициализации конструктора

У меня есть конструктор, который принимает некоторые аргументы. Я предполагал, что они были построены в указанном порядке, но в одном случае кажется, что они были построены в обратном порядке, что привело к прерыванию. Когда я изменил аргументы, программа перестала прерываться. Это пример синтаксиса, который я использую. Дело в том, что a_ нужно инициализировать перед b_ в этом случае. Можете ли вы гарантировать порядок строительства?

например

class A
{
  public:
    A(OtherClass o, string x, int y) :
      a_(o), b_(a_, x, y) { }

    OtherClass a_;
    AnotherClass b_;
};

4 ответа

Решение

Это зависит от порядка объявления переменных-членов в классе. Так a_ будет первым, потом b_ будет вторым в вашем примере.

Чтобы процитировать стандарт, для уточнения:

12.6.2.5

Инициализация происходит в следующем порядке:

...

  • Затем нестатические элементы данных должны быть инициализированы в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).

...

Стандартная ссылка для этого теперь выглядит как 12.6.2 раздел 13.3:

(13.3) - Затем не статические члены-данные инициализируются в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).

Видя другие ответы без особых подробностей об инициализации других участников, я рекомендую прочитать дополнительную информацию из стандартной ссылки 12.6.2, раздел 13 (спасибо @Adam Getchell за ссылку):

В конструкторе без делегирования инициализация выполняется в следующем порядке:

(13.1) — Во-первых, и только для конструктора самого производного класса (1.8),
виртуальные базовые классы инициализируются в том порядке, в котором они появляются при обходе слева направо в глубину направленного ациклического графа базовых классов, где «слева направо» — это порядок появления базовых классов в списке базовых спецификаторов производного класса .

(13.2) — Затем прямые базовые классы инициализируются в том порядке объявления
, в котором они появляются в списке базовых спецификаторов
(независимо от порядка mem-инициализаторов ).

(13.3) — Затем нестатические элементы данных инициализируются
в том порядке, в котором они были объявлены в определении класса
(опять же независимо от порядка mem -инициализаторов ).

(13.4) — Наконец, выполняется составной оператор тела конструктора.

Терминология:

base-specifier-list- список базовых классов для производного класса. См. раздел 10 справки.
Пример:class A : public virtual B, private C

mem-initializers— список инициализаторов членов вашего класса.
Пример:A::A() : number(1.0f), text("abc"){ /* ... */}

compound-statement- блок{}, т.е. тело конструктора.


Вот и все, просто произнес приказ:

  1. статические переменные (см. этот вопрос о stackoverflow. Порядок инициализации статических переменных C++ , а также это интересное поведение SIOF). В одной единице трансляции порядок следует за порядком объявления, в разных - решают компиляторы.
  2. виртуальные базовые классы , представленные dfs
  3. прямые базовые классы , как указано в списке производных
  4. нестатические переменные по объявлению (! не по порядку инициализаторов)
Другие вопросы по тегам