C++ порядок инициализации членов-класса

164
01 января 2020, 06:20

В каком порядке пройдет инициализация членов класса в С++? Сначала будет вызван конструктор класса или сначала будут проиницилазованы члены-класса?

class A {}
class B
{ 
public:
   B() = default;
private: 
   A a; 
   static A a0;
   int i;
   static int i0; 
}
Answer 1

Сначала будут инициализированы статические члены класса в порядке их объявления еще до первого создания объекта класса. То есть до вызова конструктора класса.

Что касается не статических членов класса, то будут они инициализированы или нет в контексте вашего примера, зависит от того, как будет создаваться объект класса.

Например, при таком создании объекта

B b1;

члены класса будут инициализированы по умолчанию, что для класса B означает, например, что член класса i на самом деле никак не будет инициализирован, так как в определении класса у этого члена отсутствует инициализатор.

Однако при таком объявлении объекта класса B

B b2 = B();

объект класса будет инициализирован по значению, что при наличии конструктора по умолчанию означает инициализацию нулем его скалярных членов класса. Так что в этом случае член класса i будет инициализирован 0.

Из стандарта C++ 17 (9.3 Initializers)

11 An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

и

8 To value-initialize an object of type T means: (8.2) — if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized...

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

Например,

struct A
{
    A() : i( 10 )
    {
        std::cout << "i = " << i << '\n';
    }
    int i;
};
Answer 2

Из стандарта:

Инициализация в неделегирующем конструкторе производится в следующем порядке:
■ (13.1) Сначала, и только для конструктора самого производного класса (1.8), инициализируются виртуальные базовые классы в порядке их появления при обходе направленного ациклического графа в направлении «снизу вверх слева направо», где «слева направо» означает очередность появления базовых классов в списке-спецификаторов-баз производного класса.
■ (13.2) Затем инициализируются непосредственные базовые классы в порядке их упоминания в списке-спецификаторов-баз (независимо от порядка mem-инициализаторов).
■ (13.3) Далее инициализируются нестатические данные-члены, в порядке их объявления в описании класса (опять-таки, независимо от порядка mem-инициализаторов).
■ (13.4) Наконец, выполняется составной-оператор тела конструктора. Замечание. Инициализация в порядке объявления обязательна, так как гарантирует разрушение подобъектов базовых классов и членов в порядке, обратном порядку их инициализации.

Т.е. в вашем классе B будет вызван конструктор A, потом - член a; i был бы проинициализирован после a (в порядке объявления), если бы вы указали его инициализатор (или в конструкторе, типа B():i(5){...}, или значение по умолчанию типа int i = 6;).

Статические члены инициализируются до начала работы с классом, однократно.

"По-моему, так" (с) Пух
Если что не так - надеюсь, гуру в стандарте меня исправят (с использованием правильной терминологии и правильных ссылок на стандарт...)

Answer 3

Если класс инициализируется при помощи конструктора, то инициализацией нестатических членов класса занимается конструктор класса. Поэтому ваш вопрос о том, что произойдет "сначала" не имеет смысла. К тому же ваш класс B может инициализироваться в обход конструктора - через value-initialization.

Порядок инициализации неинлайновых статических членов класса зависит от точки их определения. Вы не привели определений ваших статических членов вообще, поэтому говорить о порядке их инициализации невозможно. Можно лишь сказать, что эти переменные скорее всего проинициализируются перед первым их использованием (хотя в определенных случаях и с этим могут возникнуть проблемы).

READ ALSO
Конвертировать long в char array

Конвертировать long в char array

Мне нужно сконвертировать переменную типа long в char arrayКак это организовать?

164
Оптимизация многопоточности

Оптимизация многопоточности

У меня есть приложение (java, android), которое запускает N фоновых потоков Число потоков задаётся пользователемЗапуск потоков происходит в цикле...

213