Std:: map значение по умолчанию для встроенного типа
В последнее время меня смутила функция std:: map operator [].
В библиотеке MSDN говорится: "Если значение ключа аргумента не найдено, оно будет вставлено вместе со значением по умолчанию для типа данных".
Я попытался найти гораздо более точное объяснение этой проблемы. Например, здесь:
std:: значение по умолчанию для карты
На этой странице Майкл Андерсон сказал, что "значение по умолчанию сконструировано конструктором по умолчанию (нулевой конструктор параметров)".
Теперь мой квест приходит к следующему: "какое значение по умолчанию для типа сборки?". Был ли он связан с компилятором? Или есть стандарт для этой проблемы комитетом звезд С++?
Я сделал тест на Visual Studio 2008 для типа "int", и нашел, что тип "int" сконструирован со значением 0.
Ответы
Ответ 1
Это определено в стандарте, да. В этом случае карта выполняет "инициализацию по умолчанию". Как вы говорите, для типов классов, который вызывает конструктор без аргументов.
Для встроенных типов в стандарте "98" см. раздел 8.5 "Инициализаторы":
Для инициализации объекта типа T по умолчанию:
- если T не является POD...
- если T - тип массива...
- В противном случае память для объекта инициализируется нулем
И, ранее,
Для нулевой инициализации хранилища для объекта типа T означает:
- если T является скалярным типом, для хранилища установлено значение 0 (ноль), преобразованное в T
Скалярные типы:
- Арифметические типы (целочисленные, с плавающей запятой)
- Типы перечислений
- Типы указателей
- Указатель на типы членов
В частности, поведение, которое вы видите с целым числом (с инициализацией до нуля), определяется стандартом, и вы можете положиться на него.
Ответ 2
Стандарт С++ 11 по-прежнему требует, чтобы std:: map zero-initializes встроенных типов (как и предыдущий стандарт), но причины немного отличаются от причин в ответе Люка Холливелла. В частности, для "default-initialize" встроенный тип данных не означает инициализацию нуля в стандарте С++ 11, а скорее означает "ничего не делать". То, что на самом деле происходит в std::map::operator[]
, является "инициализацией значения".
Тем не менее, конечный результат в новом стандарте такой же, как в ответе Люка. Значения будут инициализированы нулем. Вот соответствующие части стандарта:
Раздел 23.4.4.3 "Доступ к элементу карты" говорит
Т & operator [] (const key_type & x);
Эффекты: Если на карте нет ключа, эквивалентного x, вставляет value_type(x, T())
в карту.
...
Выражение T()
описано в разделе 8.5
Объект, инициализатор которого представляет собой пустой набор скобок, т.е.(), должен быть инициализирован значением.
X a();
И этот тип инициализации значения описан в том же разделе
Для инициализации объекта типа типа T означает:
- если T является (возможно, cv-квалифицированным) типом класса (раздел 9) с предоставленным пользователем конструктором (12.1), тогда конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного конструктор по умолчанию);
- если T является (возможно, cv-квалифицированным) классом типа non-union без предоставленного пользователем конструктора, тогда объект инициализируется нулем и, если Ts неявно объявленный конструктор по умолчанию является нетривиальным, что конструктор.
- если T - тип массива, то каждый элемент инициализируется значением;
- , объект инициализируется нулем.
Ответ 3
Значение по умолчанию для объектов класса-типа устанавливается стандартным конструктором класса. Для встроенных типов значение по умолчанию равно 0.
Но обратите внимание, что существует разница между встроенной переменной, которая не инициализирована, и одной инициализированной значением по умолчанию. Встроенный, который не инициализирован, вероятно, сохранит любое значение в этом адресе переменной памяти в то время.
int i; // i has an arbitrary undefined value
int x = int(); // x is 0
Ответ 4
|expression: | POD type T | non-POD type T
==================================================================================================
| new T | not initialized | default-initialized
| new T() | always default-initialized | always default-initialized
| new T(x) | always initialized via a constructor | always initialized via a constructor
Насколько я знаю, stl использует новые значения T() для значений по умолчанию, поэтому он будет инициализирован по умолчанию, если int равен 0.