Зависимости в списках инициализации - PullRequest
18 голосов
/ 09 июня 2011

Это поведение хорошо определено?

class Foo
{
    int A, B;

    public:

    Foo(int Bar): B(Bar), A(B + 123)
    {
    }
};

int main()
{
    Foo MyFoo(0);
    return 0;
}

Ответы [ 3 ]

17 голосов
/ 09 июня 2011

Нет, это не определено. A будет инициализирован первым (первым в определении класса) и использует неинициализированный B.

Члены класса инициализируются в том порядке, в котором они указаны в определении класса, независимо от их порядка в списке инициализации. На самом деле, неправильно совмещать порядок определения элементов с порядком списка инициализации.

Если ваш экземпляр Foo имеет статическую длительность, как в Foo f(0); int main(){}, поведение четко определено. Объекты со статической длительностью инициализируются нулями перед любой другой инициализацией; в этом случае A и B будут 0 при запуске конструктора. После этого, однако, поведение остается таким же: сначала A, затем B, что дает A значение 123 и B значение Bar (все еще безобразно).

11 голосов
/ 09 июня 2011

Нет, порядок инициализации определяется порядком объявления в самом классе.

Из стандарта C ++ 12.6.2 [class.base.init] p5:

Инициализация должна выполняться в следующем порядке:
- Во-первых, и только для конструктора самого производного класса, как описано ниже, виртуальные базовые классы должны быть инициализированы в том порядке, в котором они отображаются при обходе слева направо по глубине направленного ациклического графа базовых классов, где « слева направо »- это порядок появления имен базовых классов в списке базовых спецификаторов производного класса.
- Затем прямые базовые классы должны быть инициализированы в порядке объявления, как они появляются в списке базовых спецификаторов (независимо от порядка mem-initializer).
- Затем нестатические элементы данных должны быть инициализированы в порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).
- Наконец, тело конструктора выполняется.
[Примечание: порядок декларирования должен обеспечивать уничтожение базовых и дочерних подобъектов в обратном порядке инициализации. ]

2 голосов
/ 09 июня 2011

Инициализация выполняется в порядке появления в объявлении, а не в том порядке, в котором вы пишете это в конструкторе.

Посмотрите на этот вопрос, он немного похож: Список инициализаторов * Аргумент * Порядок оценки

...