std :: unordered_map operator []は、存在しないキーに対してゼロ初期化を行いますか?


25

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?
}

13
@Ælex何かが初期化されているかどうかを確実にテストすることはできません
idclev 463035818

2
@Ælex本当に理解できません。どのようにして初期化されていないものにすることができますstd::optionalか?
idclev 463035818

2
@Ælexオブジェクトが初期化されているかどうかをテストする方法はありません。初期化以外の初期化されていないオブジェクトに対する操作は、未定義の動作を引き起こすためです。std::optionalノー含まれる値を保持するオブジェクトはまだ初期化されたオブジェクトです。
bolov

2
値オブジェクトはゼロで初期化されず、値で初期化されます。スカラー型の場合は同じですが、クラス型の場合は異なります。
aschepler

@bolov私は昨日、gnu 17とstd 17を使用してそれをテストしようとしました、そして奇妙なことに私が得たすべてはゼロ初期化でした。私std::optional has_valueはそれをテストすることを考えたが、それは失敗するので、あなたが正しいと思います。
Ælex

回答:


13

話しているオーバーロードに応じてstd::unordered_map::operator[][unord.map.elem]と同等です。

T& operator[](const key_type& k)
{
    return try_­emplace(k).first->second;
}

(右辺値参照を取るオーバーロードは移動するだけです ktry_emplaceはする、それ以外は同じです)

要素がkマップのキーの下に存在する場合、try_emplaceその要素へのイテレータとを返しますfalse。それ以外の場合はtry_emplace、キーの下に新しい要素を挿入し、その要素ktrue [unord.map.modifiers]にイテレータを返します。

template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);

私たちにとって興味深いのは、まだ要素がない場合です[unord.map.modifiers] / 6

それ以外の場合はvalue_­typepiecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...)

(右辺値参照をとるオーバーロードは単に移動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、引数なしからのメンバーとして作成される新しい値[pairs.pair] / 14に要約されますこれは、使用するタイプの値の直接初期化[class.base.init] / 7です。値の初期化[dcl.init] /17.4に要約される初期化子として。の値の初期化はゼロ初期化[dcl.init] / 8です。そして、自然にゼロ初期化すると、自然に0 に初期化されます[dcl.init] / 6T()intintint

つまり、コードは0を返すことが保証されています…


21

あなたがリンクしたサイトではそれは言う:

デフォルトのアロケータが使用される場合、これにより、キーはキーからコピー構築され、マップされた値は値で初期化されます。

したがって、int初期化されます

値の初期化の影響は次のとおりです。

[...]

4)それ以外の場合、オブジェクトはゼロで初期化されます

これが結果がである理由です0

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.