Залежно від того, про яке перевантаження ми говоримо, 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 ...