244

初めてマップを使用していますが、要素を挿入する方法がたくさんあることに気付きました。emplace()operator[]またはに加えて、またはを使用するinsert()ようなバリアントを使用できます。それらすべてに関する多くの情報と特定のケースに関する質問がありますが、全体像を理解することはまだできません。だから、私の2つの質問は次のとおりです。value_typemake_pair

  1. それらのそれぞれが他のものよりも優れている点は何ですか?

  2. 標準に emplace を追加する必要はありましたか? それなしでは不可能だったことはありますか?

4

5 に答える 5

17

Emplace: 右辺値参照を利用して、作成済みの実際のオブジェクトを使用します。これは、コピーまたは移動コンストラクターが呼び出されないことを意味し、LARGE オブジェクトに適しています! O(log(N)) 時間。

挿入: 標準の左辺値参照と右辺値参照のオーバーロード、挿入する要素のリストへの反復子、および要素が属する位置に関する「ヒント」があります。「ヒント」反復子を使用すると、挿入にかかる時間を一定時間に短縮できます。それ以外の場合は、O(log(N)) 時間になります。

Operator[]: オブジェクトが存在するかどうかを確認し、存在する場合はこのオブジェクトへの参照を変更し、存在しない場合は、指定されたキーと値を使用して 2 つのオブジェクトで make_pair を呼び出し、insert 関数と同じ作業を行います。これは O(log(N)) 時間です。

make_pair: ペアを作る以上のことはしません。

標準に emplace を追加する「必要」はありませんでした。c++11 では && 型の参照が追加されたと思います。これにより、移動セマンティクスの必要性がなくなり、特定のタイプのメモリ管理の最適化が可能になりました。特に、右辺値参照。オーバーロードされた insert(value_type &&) 演算子は in_place セマンティクスを利用しないため、効率が大幅に低下します。右辺値参照を処理する機能を提供しますが、オブジェクトの適切な構築という主要な目的を無視します。

于 2013-06-18T15:28:55.520 に答える
11

最適化の機会とより単純な構文は別として、挿入と埋め込みの重要な違いは、後者が明示的な変換を許可することです。(これは、マップだけでなく、標準ライブラリ全体に適用されます。)

以下に例を示します。

#include <vector>

struct foo
{
    explicit foo(int);
};

int main()
{
    std::vector<foo> v;

    v.emplace(v.end(), 10);      // Works
    //v.insert(v.end(), 10);     // Error, not explicit
    v.insert(v.end(), foo(10));  // Also works
}

これは確かに非常に具体的な詳細ですが、一連のユーザー定義の変換を扱う場合は、これを覚えておく価値があります。

于 2013-06-18T15:50:28.137 に答える