Требуется некоторое уточнение с 8.5.p7 в стандарте С++ 11

Пункт 8.5p7 Стандартных состояний С++ 11:

Для инициализации объекта типа типа T означает:

  • если T является (возможно, cv-квалифицированным) классом типа (раздел 9) с предоставленным пользователем конструктором (12.1), то конструктор по умолчанию для T называется (и инициализация плохо сформирована, если T не имеет доступного значения по умолчанию Конструктор);

  • если T является (возможно, cv-квалифицированным) классом типа non-union без созданного пользователем конструктора, тогда объект нулевой инициализированный и, если Ts неявно объявленный конструктор по умолчанию является нетривиальным, этот конструктор называется.

  • если T - тип массива, то каждый элемент инициализируется значением;

  • в противном случае объект нулевой инициализируется.

У меня проблема с пониманием символов, выделенных жирным шрифтом выше. Как дополнительный вызов T-неявного конструктора по умолчанию может изменить нулевую инициализацию, которая только что произошла в этом случае?

Ответ 1

Вот конкретный пример:

class A {
    int a;
public:
    A() : a(1) {}
};

class B {
    int b;
    A c;
};

B попадает в эту категорию - это неединичный класс класса без предоставленного пользователем конструктора. Поэтому, если a B инициализируется значением, он сначала будет инициализирован нулем (поэтому оба параметра B и c.a будут установлены в 0), а затем будет вызываться конструктор по умолчанию (который вызовет A конструктор и установите c.a в 1).

В соответствии с правилом as-if они могут быть объединены в один шаг оптимизатором (который установит B в 0 и c.a в 1), так как никто никогда не может видеть объект между нулем инициализация и конструктор по умолчанию.

Ответ 2

T может не иметь собственного явного конструктора по умолчанию, но он может произойти из U, который делает, и/или имеет член типа класса V, который делает.

Ответ 3

struct S {
    int a, b;
    S() : b(10) {}
};

struct T {
  S s;
};

int main() {
    S s{};
    T t{};
}

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

s также инициализируется значением, но s имеет предоставленный пользователем конструктор.

s.a будет иметь неопределенное значение. но t.s.a равен нулю из-за инициализации нуля, предшествующей вызову конструктора по умолчанию. Оба параметра s.b и t.s.b установлены в значение 10.