push_back
との違いについて少し混乱していますemplace_back
。
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
右辺値参照を取るオーバーロードがあるので、push_back
の目的が何にemplace_back
なるのかよくわかりません。
ベストアンサー1
訪問者のコメントに加えて:
MSCV10 によって提供される関数はvoid emplace_back(Type&& _Val)
、ご指摘のとおり と厳密に同等であるため、非準拠かつ冗長ですpush_back(Type&& _Val)
。
しかし、実際の C++0x 形式はemplace_back
非常に便利です。void emplace_back(Args&&...)
;
を取る代わりにvalue_type
、可変長引数リストを取るので、引数を完全に転送し、一時的なものをまったく使用せずにコンテナー内にオブジェクトを直接構築できるようになりました。
これは便利な機能です。RVO と移動セマンティクスがどれだけ巧妙になっても、 a がpush_back
不要なコピー (または移動) を行う可能性のある複雑なケースが依然として存在するからです。たとえば、insert()
a の従来の機能ではstd::map
、一時的な を作成し、それを a にコピーしstd::pair<Key, Value>
、それを map にコピーする必要があります。
std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";
// cross your finger so that the optimizer is really good
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString)));
// should be easier for the optimizer
m.emplace(4, anInt, aDouble, aString);
では、なぜMSVCで正しいバージョンを実装しなかったのでしょうかemplace_back
?実は私も少し前に気になったので、同じ質問をしました。Visual C++ ブログ以下は、Microsoft の Visual C++ 標準ライブラリ実装の公式メンテナーである Stephan T Lavavej からの回答です。
Q: ベータ 2 の emplace 関数は、現時点では単なるプレースホルダーのようなものですか?
A: ご存知のとおり、可変長引数テンプレートは VC10 では実装されていません。
make_shared<T>()
、タプル、 の新機能などについては、プリプロセッサ機構を使用してそれらをシミュレートします<functional>
。このプリプロセッサ機構は、使用と保守が比較的困難です。また、サブヘッダーを繰り返し含める必要があるため、コンパイル速度に大きく影響します。時間的制約とコンパイル速度の懸念の組み合わせにより、emplace 関数では可変長引数テンプレートをシミュレートしていません。可変長テンプレートがコンパイラに実装されると、emplace 関数を含むライブラリでそのテンプレートが利用されることが予想されます。私たちは準拠を非常に重視していますが、残念ながらすべてを一度に行うことはできません。
それは理解できる決定です。プリプロセッサのひどいトリックで可変長テンプレートをエミュレートしようとしたことがある人なら誰でも、これがどれほどひどいものになるか知っています。