web-dev-qa-db-ja.com

map <int、int>のデフォルト値

std::map<int,int> mapy;
++mapy[5];

mapy[5]が常に1になると仮定しても安全ですか?私のコードのように明示的に宣言されていなくても、mapy[5]は常に '++'の前に0のデフォルト値を取得しますか?

63
Bill Kotsias

[]演算子でマップにアクセスするとすぐに、キーが存在しない場合は追加されます。 int型のデフォルトの初期化子が呼び出されます-そのため、値0を取得します。

97
rep_movsd

はい、想定しても安全です。

したがって、マップの_operator[]_は次のように指定されます。([map.access])

効果:マップにxに相当するキーがない場合、マップにvalue_type(std::move(x), T())を挿入します。
戻り値:_mapped_type_のxに対応する_*this_への参照。

T()は、Tを除くすべてのvoidに対してvalue-initialisationを使用します ([expr.type.conv]/2)、およびvalue-initialisationはプリミティブに対してzero-initializationになります ([dcl.init]/7)

したがって、式は値ゼロのオブジェクトへの参照に評価されます ([dcl.init]/5)

_operator++_呼び出しは、そのオブジェクトを1にインクリメントし、1に評価します。

(すべての参照はC++ 11です。)

はい、デフォルト値はそのタイプのデフォルトになります。別のデフォルトが必要な場合は、intのように動作するが、デフォルトのコンストラクターが異なるクラスを作成できます。

8
Rasmus Kaj

Rep_Movsdの答えは単純化されすぎており、非常に多くの非常に危険な誤解につながる可能性があります。 C++のプリミティブデータ型には初期化子がありません。 Louis Brandyは、Facebookで行われた多くの一般的なC++エラーについて議論する素晴らしい講演を行いました。 std :: map <> []が実際にどのように機能するかについて対処します。

一般に、intは初期化されず、すべてのプリミティブ型のように未定義です。 std :: map <> []で使用する場合、intには値の初期化と呼ばれるプロセスで設定されたデフォルト値ゼロが設定されています。値の初期化は、一般に構造体で実際に機能するプロセスです。例えば、

struct Struct {
Struct() : memberVariable() {}
       int memberVariable;
};

Intを常にゼロに初期化します。メンバー変数が他のプリミティブ型である場合、特定の初期化値もあります。たとえば、次のタイプは、次のような値の初期化を通じて初期化されます。

bool = false
float = 0.0f
enum =(enumタイプ)0
pointer = nullポインター
メンバーへのポインター= nullメンバーポインター

明示的に初期化されていないデータを扱うときは、非常に注意してください。最後に、次のコードを検討してください

map<string, int> myMap;
cout << myMap["Foo"];

このコードは常に整数を0に初期化するだけでなく、マップに0を挿入します。簡単に要約すると、初期化されていない場合、プリミティブデータ型は未定義ですが、構造体またはマップ値の初期化などの場合、特定の値でプリミティブデータを初期化します。

3
Rachel Casey