Порядок оценки списка инициализации конструктора
У меня есть конструктор, который принимает некоторые аргументы. Я предполагал, что они были построены в указанном порядке, но в одном случае кажется, что они были построены в обратном порядке, что привело к прерыванию. Когда я изменил аргументы, программа перестала прерываться. Это пример синтаксиса, который я использую. Дело в том, что 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
- блок{}
, т.е. тело конструктора.
Вот и все, просто произнес приказ:
- статические переменные (см. этот вопрос о stackoverflow. Порядок инициализации статических переменных C++ , а также это интересное поведение SIOF). В одной единице трансляции порядок следует за порядком объявления, в разных - решают компиляторы.
- виртуальные базовые классы , представленные dfs
- прямые базовые классы , как указано в списке производных
- нестатические переменные по объявлению (! не по порядку инициализаторов)