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