Selon la surcharge dont nous parlons, std::unordered_map::operator[]
équivaut à [unord.map.elem]
T& operator[](const key_type& k)
{
return try_emplace(k).first->second;
}
(la surcharge prenant une référence rvalue se déplace simplement k
danstry_emplace
et est par ailleurs identique)
Si un élément existe sous clé k
dans la carte, try_emplace
retourne alors un itérateur à cet élément et false
. Sinon, try_emplace
insère un nouvel élément sous la clé k
, et renvoie un itérateur à celui-ci et true
[unord.map.modifiers] :
template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
Intéressant pour nous est le cas où il n'y a pas encore d'élément [unord.map.modifiers] / 6 :
Sinon, insère un objet de type value_type
construit avecpiecewise_construct, forward_as_tuple(k), forward_as_tuple(std::forward<Args>(args)...)
(la surcharge en prenant une référence rvalue se déplace juste k
en forward_as_tuple
et, encore une fois, est par ailleurs identique)
Puisque value_type
c'est un pair<const Key, T>
[unord.map.overview] / 2 , cela nous dit que le nouvel élément de carte sera construit comme:
pair<const Key, T>(piecewise_construct, forward_as_tuple(k), forward_as_tuple(std::forward<Args>(args)...));
Puisque args
est vide en venant de operator[]
, cela revient à notre nouvelle valeur étant construite en tant que membre de l' pair
argument no [pairs.pair] / 14 qui est l'initialisation directe [class.base.init] / 7 d'une valeur de type T
using ()
comme initialiseur qui se résume à l'initialisation de la valeur [dcl.init] /17.4 . L'initialisation de la valeur d'un int
est une initialisation nulle [dcl.init] / 8 . Et l'initialisation nulle de an int
initialise naturellement cela int
à 0 [dcl.init] / 6 .
Alors oui, votre code est garanti pour retourner 0…