web-dev-qa-db-ja.com

キーが存在しないマップの値を読み取るとどうなりますか?

map<string, string> dada;
dada["dummy"] = "papy";
cout << dada["pootoo"];

未定義の動作と見なされるかどうかわからないので、私は困惑しています。存在しないキーを要求するタイミングを知る方法は、代わりにfindを使用するだけですか?

60
jokoon

_map::operator[]_は、指定されたキーに対応する値のデータ構造を検索し、その参照を返します。

見つからない場合、デフォルトの構成要素を透過的に作成します。 (この動作が望ましくない場合は、代わりに_map::at_関数を使用できます。)

ここでstd :: mapのメソッドの完全なリストを取得できます:

http://en.cppreference.com/w/cpp/container/map

以下は、現在のC++標準の_map::operator[]_のドキュメントです...

23.4.4.3マップ要素アクセス

T& operator[](const key_type& x);

  1. 効果:マップにxに相当するキーがない場合、value_type(x、T())をマップに挿入します。

  2. 必要:key_typeはCopyConstructibleで、mapped_typeはDefaultConstructibleでなければなりません。

  3. 戻り値:* thisのxに対応するmapped_typeへの参照。

  4. 複雑さ:対数。

T& operator[](key_type&& x);

  1. 効果:マップにxに相当するキーがない場合、value_type(std :: move(x)、T())をマップに挿入します。

  2. 必須:mapped_typeはDefaultConstructibleでなければなりません。

  3. 戻り値:* thisのxに対応するmapped_typeへの参照。

  4. 複雑さ:対数。

63
Andrew Tomazos

インデックス演算子_key value_を使用して_[]_にアクセスしようとすると、次の2つのことが起こります。

  1. マップにはこのkeyが含まれます。したがって、対応する_key value_を返します。
  2. マップにはkeyが含まれていません。この場合、_null value_でkeyをマップに自動的に追加します。

_"pootoo"_キーがマップに存在しません。したがって、このkeyは_value = ""_(空の文字列)で自動的に追加されます。そして、プログラムは空の文字列を出力します。

ここで、マップサイズは_1_増加します。

キーを検索するには、map_name.find()を使用できます。キーが存在しない場合は、map_name.end()が返されます。余分なkeyは追加されません。

キーに値を設定する場合は、_[]_演算子を使用できます。

15
Ali Akber

未定義の動作ではありません。 operator []は、提供されたキーの値を見つけられず、その位置に値を挿入します。

7
Luchian Grigore

Operator []の場合、存在しないキーの値にアクセスしようとすると、デフォルトで構築された新しい値オブジェクトがマップに配置され、その参照が返されます。

6
Michael Kohne

mapoperator[]は非const参照を返し、2行目に示した方法でそれを使用して割り当てることができます。この方法でアクセスすると、valueタイプのデフォルトの構成要素が作成されます。

要素を見つけたい場合、より良い方法は

iterator find ( const key_type& x )

(またはconst代替)キーが見つからない場合、または使用できるコレクション内にあるかどうかだけを知りたい場合は、<map>.end()に等しいイテレータを返します

size_type count ( const key_type& x ) const

キーは一意であるため、マップでは常に1または0を返します。

2
Component 10

演算子[]が指定されたキーの値を見つけられない場合、その位置に値を挿入します。

しかし、注意する必要があります _not exist key_にアクセスして、mapKV [not_exist_key] .member_fun()などのメンバー関数を呼び出すと、プログラムがクラッシュする可能性があります。

次のようにクラスをテストする例を挙げてみましょう:

_struct MapValue{
    int val;

    MapValue(int i=0){
        cout<<"ctor: "<<i<<endl; val = i;
    }

    ~MapValue(){
        cout<<"dtor: "<<val<<endl;
    }

    friend ostream& operator<<(std::ostream& out, const MapValue& mv){
        cout<<"MapValue: "<<mv.val<<endl;
    }

    string toString(){
        cout<<"MapValue: "<<val<<endl;
    }
};
_

テストコード:

_cout<<"-------create map<int, MapValue>-------"<<endl;

map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};

cout<<"-----cout key[2]-----"<<endl;
cout<<idName[2]<<endl;

cout<<"-----cout key[5]-----"<<endl;
cout<<idName[5]<<endl;

cout<<"------- runs here means, does't crash-------"<<endl;
_

以下のように出力:

_-------create map<int, MapValue>-------
ctor: 1
ctor: 2
dtor: 2
dtor: 1
dtor: 2
dtor: 1
-----cout key[2]-----
MapValue: 2

-----cout key[5]-----
ctor: 0
MapValue: 0

-------runs here means, does't crash-------
dtor: 0
dtor: 2
dtor: 1
_

次のことがわかります。_idName[5]_は、マップ構成{5, MapValue(0)}を呼び出してidNameに挿入します。

ただし、_idName[5]_でメンバー関数を呼び出すと、プログラムはクラッシュします:

_cout<<"-------create map<int, MapValue>-------"<<endl;

map<int, MapValue> idName{{1, MapValue(1)}, {2, MapValue(2)}};


idName[5].toString();  // get crash here.


cout<<"------- runs here means, doesn't crash-------"<<endl;
_
1
Jayhello

out_of_range例外をご覧ください: http://www.cplusplus.com/reference/stdexcept/out_of_range/

これは、キーが存在しない場合にmap :: atおよびmap :: operator []がスローするものです。リンクのベクトルの例と同じ方法でキャッチできます。

次も使用できます。 http://www.cplusplus.com/reference/map/map/find/

そして、map :: endをチェックします

0
user2346536