Инициализация std::unordered_map

Когда я получаю доступ к элементу в std::unordered_map с помощью оператора [] для в первый раз он создается автоматически. Каковы (если есть) гарантии его инициализации? (Гарантированно будет инициализировано значение или только построено)?

Пример:

std::unordered_map<void *, size_t> size;
char *test = new char[10];
size[test] += 10;

Гарантировано ли size[test] 10 в конце этой последовательности?


person Suma    schedule 20.01.2012    source источник


Ответы (2)


Гарантировано ли size[test] 10 в конце этой последовательности?

Да. В последней строке вашего кода значение size[test] инициализирует элемент значением T() или, в данном случае, size_t():

C++11 23.4.4.3 доступ к элементам карты [map.access]

T& operator[](const key_type& x);

1 Эффекты: если на карте нет ключа, эквивалентного x, вставляет в карту value_type(x, T()).

Что касается T(), точный язык несколько запутан, поэтому я попытаюсь процитировать соответствующие фрагменты:

C++11 8.5.16 Семантика инициализаторов следующая.

Если инициализатором является (), объект инициализируется значением.


8.5.7 Чтобы инициализировать значение объекта типа T, необходимо:

- если T является типом класса (возможно, cv-квалифицированным) ...

- если T является (возможно, cv-квалифицированным) типом класса без объединения ...

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

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


8.5.5 Чтобы обнулить объект или ссылку типа T, необходимо:

— если T — скалярный тип (3.9), объекту присваивается значение 0 (ноль), взятое как интегральное константное выражение, преобразованное в T;

person NPE    schedule 20.01.2012
comment
Я прочитал эту часть документов, но я не был уверен в последствиях. Что означает построение по умолчанию для целочисленного типа, такого как size_t? (Можете ли вы процитировать стандарт, желательно?) - person Suma; 20.01.2012
comment
@Suma: интегральные типы не являются типами классов, поэтому у них нет конструкторов. Инициализация значений этих типов равна инициализации нулями. (Глава 8.) - person Kerrek SB; 20.01.2012
comment
@KerrekSB, вы уверены, что не путаете C++ с Java? Встроенные функции не конструируют по умолчанию нулевое значение. - person spraff; 20.01.2012
comment
Инициализация значений этих типов равна инициализации нулями, это ясно, но документы оператора [] не говорят об инициализации значений, а только о конструкции по умолчанию. Я не эксперт по стандартам, я думаю, вы правы, и это означает то же самое, но можно ли показать пошагово стандартными цитатами? - person Suma; 20.01.2012
comment
Как вы писали в предыдущей версии, [] гарантирует построение по умолчанию. Сейчас вы говорите об инициализации значения, но я не вижу, откуда берется гарантия инициализации значения в случае этого оператора. (Я бы очень хотел, чтобы это было правдой, это делает мой код построения гистограммы намного проще, но я хотел бы не полагаться на какое-то неопределенное поведение). - person Suma; 20.01.2012
comment
Втф? Это новое для С++ 11? Я был уверен, что встроенные функции не имеют значений по умолчанию, принцип отсутствия накладных расходов. - person spraff; 20.01.2012
comment
@spraff: инициализация значения влечет за собой обнуление, и Стандарт здесь гарантирует инициализацию значения. Обычно в общем встроенные оставляются как есть, но в частном случае контейнеров STL они инициализируются значением. Точно так же, если вы вызовете std::vector<int> v(10);, вы получите 10 нулей. - person Matthieu M.; 20.01.2012
comment
@spraff: инициализация значений была новой в C++03 (одно из очень немногих изменений по сравнению с C++98). - person Mike Seymour; 20.01.2012
comment
Фу. Не могу сказать, что одобряю это. Построение вектора теперь O (n). - person spraff; 20.01.2012

Какая разница? Инициализация значения для объектов типа класса влечет за собой конструкцию по умолчанию, поэтому ответ "оба". Для карты <K, V> новый объект будет инициализирован с помощью V().

Все стандартные контейнеры инициализируют новые элементы с помощью инициализации значения или прямой инициализации (последнее возможно с помощью конструкции копирования). Новые стандартные элементы контейнера не могут находиться в «неинициализированном» состоянии (т. е. нет механизма, который по умолчанию инициализирует элементы).

person Kerrek SB    schedule 20.01.2012
comment
Я предположил, что построен в том смысле, что когда я использую переменную-член int в классе, конструктор класса по умолчанию не инициализирует значение. Думаю, вы правы, но гарантируется ли инициализация значения построенной по умолчанию фразой? Что, если V будет POD? Будет ли он построен по умолчанию (т.е. неинициализирован) или инициализирован значением? - person Suma; 20.01.2012
comment
@Suma: V инициализируется значением, поэтому, если V является фундаментальным, он инициализируется нулем, а если он имеет тип класса, он создается по умолчанию. Для составных типов правила применяются рекурсивно. - person Kerrek SB; 20.01.2012