web-dev-qa-db-ja.com

マップに要素を挿入する推奨方法

可能性のある複製:
STLマップでは、[]?よりもmap :: insertを使用した方が良いですか?

マップに要素を挿入するとき、推奨される方法は何だろうと思っていました。したほうがいい

map[key] = value;

または

map.insert(std::pair<key_type, value_type>(key, value));

次の簡単なテストを行いました。

#include <map>
#include <string>
#include <iostream>

class Food {
public:
    Food(const std::string& name) : name(name) { std::cout << "constructor with string parameter" << std::endl; }
    Food(const Food& f) : name(f.name) { std::cout << "copy" << std::endl; }
    Food& operator=(const Food& f) { name = f.name; std::cout << "=" << std::endl; return *this; } 
    Food() { std::cout << "default" << std::endl; }
    std::string name;
};

int main() {
    std::map<std::string, Food> m0;

/*
1) constructor with string parameter
2) copy
3) copy
4) copy
*/
    m0.insert(std::pair<std::string, Food>("Key", Food("Ice Cream")));

/*
1) constructor with string parameter
2) default
3) copy
4) copy
5) =
*/
    // If we do not provide default constructor.
    // C2512: 'Food::Food' : no appropriate default constructor available
    m0["Key"] = Food("Ice Cream");
}
  1. メンバー関数insertを使用することで、より少ない値の関数呼び出しが関与することに気付きます。では、insertを使用することをお勧めしますか?
  2. map[key] = valueウェイが使用されているのに、なぜデフォルトのコンストラクターが必要なのですか?

insertは既存のキーと値のペアを上書きしませんが、map[key] = valueは上書きします。しかし、両方から選択しようとするとき、これが私が考慮に入れる唯一の要因ですか?

どう?

  1. パフォーマンス
  2. 値のデフォルトコンストラクタの利用可能性
  3. ???
90
Cheok Yan Cheng
  1. insertは推奨される方法ではありません-マップに挿入する方法の1つです。 operator[]との違いは、insertが要素がマップに挿入されているかどうかを判断できることです。また、クラスにデフォルトのコンストラクタがない場合、insertを使用する必要があります。
  2. マップは要素が存在するかどうかをチェックするため、operator[]にはデフォルトのコンストラクタが必要です。そうでない場合は、デフォルトのコンストラクターを使用して作成し、参照(またはconst参照)を返します。

マップコンテナでは重複したキー値は許可されないため、挿入操作では、挿入された各要素について、同じキー値を持つコンテナに別の要素が既に存在するかどうかがチェックされます。仕方。

63
BЈовић

新しい要素を挿入する場合は、insertを使用します。 insertは既存の要素を上書きしません。以前に存在していた要素がなかったことを確認できます。

if ( !myMap.insert( std::make_pair( key, value ) ).second ) {
    //  Element already present...
}

既存の要素を上書きする場合は、[]を使用します。

myMap[ key ] = value;
assert( myMap.find( key )->second == value ); // post-condition

このフォームは、既存のエントリを上書きします。

45
James Kanze

引用するには:

マップコンテナでは重複したキー値は許可されないため、挿入操作では、挿入された各要素について、同じキー値を持つコンテナに別の要素が既に存在するかどうかがチェックされます。仕方。

したがって、キーがすでに存在する場合、挿入は値を変更しません。[] operatorは変更されます。

編集:

これは別の最近の質問を思い出させます-[] operatorの代わりにat()を使用してベクターから値を取得する理由。明らかに、[] operatorがそうではないのに対し、インデックスが範囲外の場合、at()は例外をスローします。このような状況では、すべての詳細が提供されるため、関数のドキュメントを参照するのが常に最善です。しかし、一般に、まったく同じことを行う2つの関数/演算子はありません(または少なくともそうすべきではありません)。

私の推測では、内部では、insert()は最初にエントリをチェックし、その後は[] operatorを使用します。

13
Luchian Grigore

map[key] = valueは、構文を簡単にするために提供されています。読み書きが簡単です。

デフォルトのコンストラクターが必要な理由は、map[key]が割り当ての前に評価されるためです。キーがマップに存在しなかった場合、新しいキーが(デフォルトのコンストラクターで)作成され、その参照がoperator[]から返されます。

9
x13n