[解決済み】c++のmapでinsertとemplaceとoperator[]の比較
質問
初めてマップを使うのですが、要素を挿入する方法がたくさんあることに気づきました。例えば
emplace()
,
operator[]
または
insert()
を使用するようなバリエーションもあります。
value_type
または
make_pair
. どれも多くの情報があり、特定のケースについての質問もありますが、やはり全体像が理解できません。
そこで、2点質問です。
-
それぞれ、他と比べてどんなメリットがあるのでしょうか?
-
emplaceを標準搭載する必要性はあったのでしょうか?また、emplaceがなければできなかったことはありますか?
解決方法は?
地図という特殊なケースにおいて、以前の選択肢は2つしかありませんでした。
operator[]
と
insert
(の異なるフレーバー)。
insert
). そこで、これらの説明を始めます。
その
operator[]
は
検索または追加
演算子です。与えられたキーを持つ要素がマップ内に存在するかどうかを試し、存在すれば格納されている値への参照を返します。存在しない場合は、デフォルトの初期化でその場所に挿入された新しい要素を作成し、それへの参照を返します。
は
insert
関数 (単一要素フレーバーの場合) は
value_type
(
std::pair<const Key,Value>
) を使用すると、キー (
first
メンバー)を挿入しようとする。なぜなら
std::map
は重複を許さないので、既存の要素がある場合は何も挿入されません。
両者の違いとしてまず挙げられるのは
operator[]
は、デフォルトで初期化された
値
そのため、デフォルトで初期化できない値型には使えません。両者の第二の違いは,与えられたキーを持つ要素が既に存在する場合にどうなるかである。これは
insert
関数はマップの状態を変更せず、その代わりに要素へのイテレータを返します(そして、その要素への
false
挿入されなかったことを示す)。
// assume m is std::map<int,int> already has an element with key 5 and value 0
m[5] = 10; // postcondition: m[5] == 10
m.insert(std::make_pair(5,15)); // m[5] is still 10
の場合は
insert
のオブジェクトである。
value_type
これは様々な方法で作成することができます。適切な型を用いて直接構築することもできますし、また、その型から任意のオブジェクトを渡すこともできます。
value_type
を構築することができ、そこで
std::make_pair
を簡単に作成することができるようになり、活躍の場が広がっています。
std::pair
オブジェクトを作成することができます。
以下の呼び出しの正味の効果は 同様 :
K t; V u;
std::map<K,V> m; // std::map<K,V>::value_type is std::pair<const K,V>
m.insert( std::pair<const K,V>(t,u) ); // 1
m.insert( std::map<K,V>::value_type(t,u) ); // 2
m.insert( std::make_pair(t,u) ); // 3
しかし、この2つは実は同じではないのです...。[1]と[2]は実は同じなのです。どちらの場合も、コードは同じ型の一時的なオブジェクトを作成します (
std::pair<const K,V>
) に渡し、それを
insert
関数を使用します。この
insert
関数は、バイナリサーチツリー内に適切なノードを作成し、そのノードに
value_type
の部分を引数からノードに移す。を使う利点は
value_type
は、まあ
value_type
いつも
一致
value_type
の型を間違えないようにしましょう。
std::pair
の引数です!
違いは[3]にあります。この関数は
std::make_pair
は、テンプレート関数で
std::pair
. シグネチャは
template <typename T, typename U>
std::pair<T,U> make_pair(T const & t, U const & u );
には意図的にテンプレート引数を与えていません。
std::make_pair
というのは、これが一般的な使い方だからです。そしてその意味するところは、テンプレート引数は呼び出しから推測されるもので、この場合は
T==K,U==V
を呼び出したので
std::make_pair
が返されます。
std::pair<K,V>
(欠落している
const
). 署名には
value_type
というのは
閉じる
を呼び出したときの戻り値と同じではありません。
std::make_pair
. 十分に近いので、正しい型のテンポラリを作成し、それをコピーして初期化します。それが今度はノードにコピーされ、合計2つのコピーが作成されます。
これは、テンプレートの引数を指定することで修正できます。
m.insert( std::make_pair<const K,V>(t,u) ); // 4
しかし、これでは、ケース[1]の明示的な型付けと同じように、やはりエラーになりやすいのです。
ここまでは、さまざまな方法で
insert
を作成する必要があること。
value_type
を外部で作成し、そのオブジェクトをコンテナにコピーします。あるいは
operator[]
の場合、型は
デフォルトコンストラクタブル
と
割り当て可能
(のみ(意図的に
m[k]=v
) が必要で、1つのオブジェクトのデフォルトの初期化と
コピー
をそのオブジェクトに入れる。
C++11 では、可変個体テンプレートと完全な転送により、コンテナに要素を追加する新しい方法があります。
配置
(create in place)といいます。そのため
emplace
関数は、基本的に同じことをします。
ソース
から
コピー
をコンテナに格納する場合、この関数はコンテナに格納されたオブジェクトのコンストラクタに転送されるパラメータを受け取ります。
m.emplace(t,u); // 5
5]では
std::pair<const K, V>
は作成されず
emplace
への参照ではなく
t
と
u
オブジェクトに渡されます。
emplace
のコンストラクタに転送します。
value_type
サブオブジェクトを作成します。この場合
いいえ
のコピーです。
std::pair<const K,V>
の利点です。
emplace
をC++03の代替品と比較した場合。の場合と同様に
insert
は、マップの値を上書きすることはありません。
私が考えもしなかった興味深い問題は、どのように
emplace
は、実際にマップに対して実装することができ、それは一般的なケースにおいて単純な問題ではありません。
関連
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み] とは何ですか! (not not)演算子とは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] JavaScriptに「NULL合体」演算子はありますか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】JavaScriptの比較では、どちらの等号演算子(== vs ===)を使うべきですか?
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー