_typedef map<KeyType, ValType> KVMap;
KVMap kvmap;
kvmap.insert( KVMap::value_type( key, val ) );
kvmap.insert( make_pair( key, val ) );
_
STLマップに挿入する上記のオプションのどれが常に速いですか?どうして?
注:insert()
は、キーと値のペアをマップに追加する(更新しない)ために_[]=
_を使用するよりも高速であることをよく知っています。私のクエリは更新ではなく追加に関するものであると想定してください。したがって、私はそれをinsert()
に制限しました。
このため、最初は'epsilon-faster'になる可能性があります(標準の23.3.1から):
typedef pair<const Key, T> value_type;
[...]
pair<iterator, bool> insert(const value_type& x);
最初のバージョンでは、std::map<K,V>::insert
が期待する適切なタイプを直接作成します。
2番目のバージョンでは、std::pair
テンプレートコンストラクターを使用した変換が含まれます。実際、std::make_pair
はテンプレート引数をKeyType
とValType
に推測する可能性が高いため、std::pair<KeyType, ValType>
を返します。
これは、std::map<K,V>::insert
のパラメータタイプであるstd::pair<const KeyType, ValType>
とは一致しません(違いはconst
で修飾されています)。 std::pair
変換コンストラクターは、std::pair<const K, V>
からstd::pair<K, V>
を作成するために使用されます。
公平を期すために、違いを測定することすらできないと思います(そして、人気のあるコンパイラーが実際にこれらに対して異なるコードを生成するかどうかさえわかりません)。
実際には、value_type
よりもmake_pair
に対して行われるべき議論があります。これは、さまざまな不可解な理由により、make_pair
が引数を値で受け入れるためです。一方、value_type
のエイリアスであるstd::pair<const Key, value>
には、const参照によって渡された引数を使用してコンストラクターが呼び出されます。 make_pair
の値渡しと参照渡しの比較では、効率が低下する可能性があります。これは、理論的にはプログラムに顕著な影響を与える可能性があります。
make_pair
で心配すべきもう1つの問題は、make_pair
は通常、map
内に必要なstd::pair<Key, Value>
に対してタイプstd::pair<const Key, Value>
のペアを作成することです。これは、変換を正しく機能させるために、今度はpair
の別の不要なコピーが作成されている可能性があることを意味します。
つまり、make_pair
を使用すると、キーと値の2つの完全に不要なコピーが作成される可能性がありますが、value_type
コンストラクターを使用するとコピーが作成されません。
これは単なる補足です。
insert( make_pair(...) )
は、他の回答者が言及した理由により、概念的にコピーコンストラクターを4回呼び出します。
insert( value_type(...) )
はコピーコンストラクターを2回呼び出します。
_operator[]
_は、通常の実装では、デフォルトのコンストラクターを1回呼び出し、コンストラクターを2回コピーします。デフォルトのコンストラクターは、insert( value_type( ..., mapped_type() ) )
の_operator[]
_内で呼び出されます。コピーコンストラクタは、insert()
の引数(pair
)をコピーするために1回呼び出され、マップの内部ノードをコピー構築するために1回呼び出されます。
したがって、insert
を_make_pair
_と一緒に使用する場合、追加してもinsert
が常に_operator[]
_よりも速いとは言えません。おそらく、状況によるでしょう。ご存知かもしれませんが、上記を考慮して、emplace
が新しい標準として提案されました。
それらは基本的に同じものです。 _KVMap::value_type
_は_std::pair<KeyType, ValType>
_のtypedefであるため、コンストラクターを呼び出すだけです。 _std::make_pair
_は、コンストラクターを呼び出すだけのテンプレート関数です(テンプレートタイプは無料の関数では推定できますが、コンストラクターでは推定できないために存在します)。信じられないほど標準的な最適化がすべて行われると、違いが生じる理由はありません。
あなたがどのようにテストしているのかわかりませんが、それを間違って行う方法はたくさんあります。
insert()
と_operator[]
_を介した割り当てについては、後者は概念的にさらに多くの作業を行う必要があります(この方法で新しい要素を追加すると、最初にデフォルトで要素を作成し、次にその上に割り当てます)が、ValType
によっては、基本的に同じものに再び最適化される可能性があります。