push_back vs emplace_back 質問する

push_back vs emplace_back 質問する

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 関数を含むライブラリでそのテンプレートが利用されることが予想されます。私たちは準拠を非常に重視していますが、残念ながらすべてを一度に行うことはできません。

それは理解できる決定です。プリプロセッサのひどいトリックで可変長テンプレートをエミュレートしようとしたことがある人なら誰でも、これがどれほどひどいものになるか知っています。

おすすめ記事