2010-02-11 3 views
4

Это проблема, с которой я часто сталкиваюсь. Следующие примеры иллюстрирует это:Инициализация членов с членами

struct A { 
    int m_SomeNumber; 
}; 

struct B { 
    B(A & RequiredObject); 
private: 
    A & m_RequiredObject; 
}; 

struct C { 
    C(); 
private: 
    A m_ObjectA; 
    B m_ObjectB; 
}; 

Реализация конструктора C выглядит примерно так:

C::C() 
: B(m_ObjectA) 
{ } 

Поскольку порядок инициализации не определен, m_ObjectA может быть инициализирован, когда конструктор m_ObjectB вызывается, что приводит к неопределенному поведению. Одним из способов заставить определенный порядок инициализации было бы сделать указатели членов и инициализировать их в теле конструктора, тем самым вызывая правильный порядок, но это уродливо по нескольким причинам. Есть ли способ заставить определенный порядок инициализации использовать список инициализации конструктора? Если нет, есть ли у вас какие-либо другие рекомендации по его устранению.

ответ

12

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

Напротив, она хорошо определена. Порядок инициализации равен порядку, в котором переменные-члены объявляются в вашем классе (и это независимо от фактического порядка списка инициализации! Поэтому рекомендуется, чтобы порядок списка инициализации соответствовал порядку объявлений избегайте неприятных сюрпризов).

+0

ну, я думал иначе. Спасибо за быстрый ответ! –

+1

Я бы добавил, что это довольно хрупкое, так как ваша уверенность в упорядоченности может быть неочевидной для читателя. Поэтому, по крайней мере, я бы добавил комментарий к определению m_objectB к эффекту «должен быть определен после m_objectA». – peterchen

+0

@peterchen: поэтому порядок списка инициализации должен действительно соответствовать порядку декларации. –