Залежно від того, про яке перевантаження ми говоримо, std::unordered_map::operator[]
еквівалентно [unord.map.elem]
T& operator[](const key_type& k)
{
return try_emplace(k).first->second;
}
(Перевантаження приймає RValue-посилання просто переміщається k
в try_emplace
і в іншому ідентичні)
Якщо елемент існує під ключем k
на карті, то try_emplace
повертає ітератор до цього елемента і false
. В іншому випадку try_emplace
вставляє новий елемент під ключ k
і повертає ітератор до цього та true
[unord.map.modifiers] :
template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
Для нас цікавий випадок, коли ще немає елемента [unord.map.modifiers] / 6 :
В іншому випадку вставляє об’єкт типу, value_type
побудований ізpiecewise_construct, forward_as_tuple(k), forward_as_tuple(std::forward<Args>(args)...)
(Перевантаження приймає RValue-посилання просто переміщається k
в forward_as_tuple
і, знову ж , в іншому ідентичні)
Оскільки value_type
це pair<const Key, T>
[unord.map.overview] / 2 , це говорить нам, що новий елемент карти буде побудований як:
pair<const Key, T>(piecewise_construct, forward_as_tuple(k), forward_as_tuple(std::forward<Args>(args)...));
Оскільки args
порожній під час приходу operator[]
, він зводиться до нашого нового значення, що будується як член pair
аргументу від аргументів [pair.pair] / 14, що є прямою ініціалізацією [class.base.init] / 7 значення типу T
за допомогою ()
як ініціалізатор, який зводиться до значення ініціалізації [dcl.init] /17.4 . Значення ініціалізації int
нуля ініціалізації [dcl.init] / 8 . І нульова ініціалізація int
природно ініціалізує це int
до 0 [dcl.init] / 6 .
Так що так, ваш код гарантовано поверне 0 ...