Является ли инициализация значения частью стандарта C++98? Если нет, то почему он был добавлен в стандарт C++03?

Ура и чт. - Альф сделал комментарий в этом ответе, что инициализация значения, возможно, является новой функцией C++03 по сравнению с C++. 98. Интересно, что он имел в виду.

Является ли инициализация значения частью C++98? Он присутствует в концепции, но не в названии? Почему он был добавлен в стандарт C++03?

У меня есть копия стандарта 03 года, но не стандарта 98 года. Вот определение инициализации по умолчанию и инициализации значения.

Инициализация по умолчанию объекта типа T означает:

- если T не является типом класса POD (пункт 9), вызывается конструктор по умолчанию для T (и инициализация является некорректной, если T не имеет доступного конструктора по умолчанию);

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

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

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

- если T является типом класса (раздел 9) с конструктором, объявленным пользователем (12.1), то вызывается конструктор по умолчанию для T (и инициализация некорректна, если у T нет доступного конструктора по умолчанию);

- если T является типом класса без объединения без объявленного пользователем конструктора, то каждый нестатический член данных и компонент базового класса T инициализируется значением;

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

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

Я предполагаю, что в '98 была инициализация по умолчанию, но не инициализация значения, и что между ними есть некоторая ключевая разница. Честно говоря, у меня возникли проблемы с разбором стандарта здесь, и я не понимаю разницы между определениями.


person Praxeolitic    schedule 08.12.2014    source источник


Ответы (1)


Цитируя стандартный документ ISO/IEC 14882:1998 (который был отозван из ИСО):

Чтобы инициализировать по умолчанию объект типа T, нужно:

  • если T не является типом класса POD (пункт 9), вызывается конструктор по умолчанию для T (и инициализация является неправильной, если T не имеет доступного конструктора по умолчанию);
  • если T является типом массива, каждый элемент инициализируется по умолчанию;
  • в противном случае хранилище для объекта инициализируется нулями.

И в пункте 7:

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

Подробности о причинах изменения можно найти в отчет о дефекте, из-за которого это произошло:

Это определение подходит для локальных переменных, но не для объектов, которые инициализируются в результате выполнения выражений формы T(), потому что объекты, получаемые такими выражениями, будут немедленно скопированы и, следовательно, должны иметь значения, которые гарантированно копируются.
С этой целью предлагаю добавить следующий новый текст в 8.5, пункт 5:

Чтобы инициализировать значение объекта типа T, нужно:

  • если T является типом класса (пункт 9 [класс]) с конструктором, объявленным пользователем (12.1), то вызывается конструктор по умолчанию для T (и инициализация является неправильной, если T не имеет доступного конструктора по умолчанию);
  • если T является типом класса без объявленного пользователем конструктора, то каждый нестатический член данных и компонент базового класса T инициализируется значением;
  • если T является типом массива, то каждый элемент инициализируется значением;
  • в противном случае хранилище для объекта инициализируется нулями.

Кроме того, я предлагаю изменить «инициализацию по умолчанию» на «инициализацию значения» в 5.2.3, пункт 2.

И после этого историческое объяснение:

Древняя история

Однажды разработчик компилятора AT&T по имени Лора Ивз спросила меня: «Каким должно быть значение int()?». Моей первой мыслью было, что оно должно быть таким же, как у x после того, как я сказал:

int x;

но вскоре я понял, что это определение не годится. Причина в том, что x имеет неопределенное значение (при условии, что это локальная переменная), но мы не возражаем против того, что x неопределенно, потому что мы предположительно собираемся присвоить значение x перед тем, как использовать его. Напротив, int() лучше не иметь неопределенного значения, потому что копирование такого значения имеет неопределенный эффект. Было бы глупо запрещать компилятору помечать int() во время компиляции, только чтобы позволить ему помечать его во время выполнения! […]

person Columbo    schedule 08.12.2014
comment
У тебя вышло. Я предлагаю включить некоторые обоснования из DR в ваш ответ, чтобы сделать его самодостаточным. Дайте мне знать, когда вы это сделаете, чтобы я мог проголосовать за вас. :) - person Lightness Races in Orbit; 08.12.2014
comment
Раздражающая вещь в версии C++98 заключается в том, что если у вас есть класс, содержащий переменные std::string и несколько переменных int, нет никакого способа инициализировать целые числа нулями, кроме как явно перечислить их все в списке инициализаторов конструктора. - person M.M; 08.12.2014
comment
@MattMcNabb Я не следил. Перечислить их все в списке инициализаторов, а не делать что? Если вы не перечислите их в списке инициализаторов в С++ 03, инициализируются ли они нулями? - person Praxeolitic; 08.12.2014
comment
@Praxeolitic в C++98 T() не инициализирует нулями целые числа (если T также содержит строки), это проявляется во многих идиомах, например. T t = T(); или T t; t = T();. Еще одно раздражающее место см. здесь - person M.M; 08.12.2014