Cppreference.comによると、 std::map::operator[]
存在しない値の場合、ゼロ初期化を行います。
ただし、同じサイトでは std::unordered_map::operator[]
ですが、これに依存する例があります。
もちろん、これは単なる参考サイトであり、標準ではありません。それで、以下のコードは大丈夫ですか?
#include <unordered_map>
int main() {
std::unordered_map<int, int> map;
return map[42]; // is this guaranteed to return 0?
}
話しているオーバーロードに応じて、_std::unordered_map::operator[]
_は [[unord.map.elem] と同等です。
_T& operator[](const key_type& k)
{
return try_emplace(k).first->second;
}
_
(右辺値参照を受け取るオーバーロードは、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 :
それ以外の場合は、
piecewise_construct, forward_as_Tuple(k), forward_as_Tuple(std::forward<Args>(args)...)
で作成された_value_type
_型のオブジェクトを挿入します
(右辺値参照をとるオーバーロードは、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)...));
_
_operator[]
_から来るときはargs
が空なので、これはつまり、引数なしでpair
のメンバーとして構築されている新しい値 [pairs.pair]/14 直接初期化 [[class.base.init]/7 _()
_を初期化子として使用してT
型の値を初期化して値を初期化する [dcl.init] /17.4 。 int
の値の初期化はゼロ初期化 [dcl.init]/8 です。そして、int
のゼロ初期化は、そのint
を自然に0に初期化します [dcl.init]/6 。
つまり、コードは0を返すことが保証されています…
あなたがリンクしたサイトではそれは言う:
デフォルトのアロケータが使用される場合、これにより、キーはキーからコピー構築され、マップされた値は値で初期化されます。
したがって、int
は value-initialized です。
値の初期化の影響は次のとおりです。
[...]
4)それ以外の場合、オブジェクトはゼロで初期化されます
これが結果が0
である理由です。