Требуется некоторое уточнение с 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.