Значение инициализации по умолчанию изменено в С++ 11?
С++ 2003 8.5/5 говорит:
Для инициализации объекта типа T по умолчанию:
- если T - тип класса не-POD (раздел 9), вызывается конструктор по умолчанию для T (и инициализация плохо сформированный, если T не имеет доступного конструктора по умолчанию);
- если T - тип массива, каждый элемент инициализируется по умолчанию;
- в противном случае объект с нулевой инициализацией.
[Акцент добавлен.]
Сценарий С++ 2011 изменил последний элемент на
- в противном случае не выполняется инициализация.
Это похоже на то, что это будет изменение для некоторых программ. Было ли это намеренно?
Edit
Вот код, который мотивирует этот вопрос:
class Foo {
public:
Foo() : m_values() {}
int m_values[3];
};
До С++ 11 я думал, что явное упоминание m_values
в конструкторе по умолчанию будет инициализировать этот массив по умолчанию. И поскольку элементы массива являются скалярными, я ожидал, что для обозначения значений все значения равны 0.
В С++ 11, похоже, больше нет гарантии, что это произойдет. Но, возможно, как указывает Mooing Duck в комментариях, возможно, это уже не случай инициализации по умолчанию, а какая-то другая форма, которая сохраняет ожидаемое поведение. Цитаты приветствуются.
Ответы
Ответ 1
Конечные эффекты почти одинаковы. В С++ 03 использование инициализации по умолчанию было ограничено типом класса не-POD, поэтому последний пункт никогда не применялся. В С++ 11 стандарт упрощает формулировку, устраняя условие относительно того, где использовалась инициализация по умолчанию, и изменяет определение инициализации по умолчанию, чтобы охватить все случаи, чтобы соответствовать тому, что было раньше.
Ответ 2
В соответствии с cppreference.com (поскольку он использует более дружественный язык, чем стандарт):
Инициализация по умолчанию выполняется в трех ситуациях:
3), когда базовый класс или нестатический элемент данных не упоминается в список инициализатора конструктора и этот конструктор вызывается.
Инициализация значения выполняется в трех ситуациях:
3,7), когда инициализируется нестатический элемент данных или базовый класс используя инициализатор элемента с пустой парой круглых скобок or braces (since C++11)
Обратите внимание, что часть С++ 11 принадлежит or braces
, а не всему абзацу.
и
Для инициализации объекта типа типа T:
- если T - тип массива, то каждый элемент инициализируется значением; - в противном случае объект инициализируется нулем
Итак, в С++ 11 инициализация по умолчанию не инициализирует нуль, а инициализирует значение.
Ответ 3
Строго говоря, определение инициализации по умолчанию изменилось с С++ 03 на С++ 11. Но нужно также учитывать, что изменились ситуации, когда объект _default-initialize_d изменился:
§8.5p9 С++ 03:
Если для объекта не задан инициализатор, а объект имеет (возможно, cv-квалифицированный) тип класса не-POD (или его массив), объект должен быть инициализирован по умолчанию; если объект имеет тип const-type, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если для нестатического объекта не указан инициализатор, объект и его подобъекты, если они есть, имеют неопределенное начальное значение; если объект или какой-либо из его подобъектов имеют тип const-specific, программа плохо сформирована.
§8.5p11 С++ 11 состояний:
Если для объекта не задан инициализатор, объект инициализируется по умолчанию; если инициализация не выполняется, объект с автоматической или динамической продолжительностью хранения имеет неопределенное значение.
Как уже указывал @JamesKanze, инициализация по умолчанию выполняется в С++ 03, если не задан инициализатор для объекта класса не-POD. В С++ 11 объект (произвольного типа) инициализируется по умолчанию, если не указан инициализатор. Из-за этого изменения, определение инициализации по умолчанию также необходимо было изменить, чтобы быть совместимым с С++ 03.
Ваш пример не имеет ничего общего с инициализацией по умолчанию. Всегда было, что объект, инициализатор которого представляет собой пустой набор круглых скобок, инициализируется значением.