В зависимости от того, о какой перегрузке мы говорим, 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
из аргументов from no [pair.pair] / 14, что является прямой инициализацией [class.base.init] / 7 значения типа, T
используя ()
как инициализатор, который сводится к инициализации значения [dcl.init] /17.4 . Значением инициализации int
является нулевая инициализация [dcl.init] / 8 . И нулевая инициализация int
естественно инициализирует это int
к 0 [dcl.init] / 6 .
Так что да, ваш код гарантированно вернет 0 ...