読者です 読者をやめる 読者になる 読者になる

C++0x Placement Insert(配置挿入)

C++

C++0x では、各コンテナに emplace/emplace_back/emplace_front/emplace_hint というメンバ関数が追加されます。


こういうクラスがあった場合

struct something {
    something(int, int, int);
};

something をコンテナの要素として追加する場合、 C++03 では以下のようにしていました。

vector<something> v;
v.push_back(something(1, 2, 3));

この方法では、 something のコンストラクタによる一時オブジェクトの生成と、コピーのコストが発生します。


Placement Insert では、可変引数テンプレートによって要素型のコンストラクタ引数を受け取ることで
要素をコンテナ内で一度だけ生成し、コピーのコストをなくします。

vector<something> v;
v.emplace_back(1, 2, 3); // emplace_backの内部でsomething(1, 2, 3)が呼ばれる

重いオブジェクトを要素とするコンテナでは、 Placement Insert は非常に重要になります。



ただし、 Placement Insert にはいくつか注意事項があります。


【explicitの問題】
コンストラクタの引数を受け取るため、 explicit なコンストラクタでも暗黙に呼び出せるように見えてしまいます。

struct something {
    explicit something(int);
};

vector<something> v;
v.emplace_back(3); // 内部でsomething(3)が"明示的に"呼び出される


【0問題】
可変引数テンプレートを使用しているため、ヌルポインタのために 0 (NULLマクロ含む)を渡そうとすると
テンプレートによって int に推論されてしまいます。
なので、 Placement Insert にヌルポインタを渡す場合は、 nullptr を使用しましょう。

struct something {
    something(int*);
};

vector<something> v;
v.emplace_back(0);       // エラー!
v.emplace_back(NULL);    // エラー!
v.emplace_back(nullptr); // OK

emplace_back は push_back の Placment Insert 版
emplace_front は push_front の Placement Insert 版
emplace は insert の Placement Insert 版
emplace_hint は insert の Placement Insert 版で、第1引数で const_iterator を受け取る(連想コンテナ用)

です



N2680 Proposed Wording for Placement Insert (Revision 1)(日本語訳)

コンストラクタの引数をとるpush_back

Placement Insertの問題

C++0x言語拡張まとめ