web-dev-qa-db-ja.com

C ++:Stack Push()vs emplace()

_std::stack_にPush()またはemplace()を使用することの違いを理解しようとしています。

_std::stack<int>_を作成する場合、integerはプリミティブ型であり、Push()が構築するものは何もないため、emplace()を使用すると考えていました。

ただし、_std::stack<string>_を作成している場合は、_std::string_がオブジェクトであるため、emplace()を選択します。

これは正しい使い方ですか?

22
Joshua Oliphant

Emplace_backが何をするかを完全に理解するには、最初に可変長テンプレートと右辺値参照を理解しなければなりません。

これは、最新のC++ではかなり高度で深い概念です。地図上では、「ドラゴンがいる」というラベルが付けられます。

あなたはC++を初めて使い、このことを学ぼうとしていると言います。これはあなたが探しているかもしれない答えではないかもしれませんが、ここではこの詳細を飛ばして、変数テンプレートと右辺値参照に頭を包んだ後で戻ってくるべきです。その後、それはすべて理にかなっているはずです。

ただし、整数のような単純な基本型を含むコンテナの場合、違いはほとんどありません。コンテナーの型が、複雑なコンストラクターやコピーコンストラクターを備えた大きく洗練されたクラスである場合に違いが生じます。

Pushまたはemplaceの最終結果は、まったく同じ100%です。コンテナは、それに追加された別の要素を取得します。違いは、要素の由来です。

1)プッシュは既存の要素を取得し、そのコピーをコンテナに追加します。シンプルでわかりやすい。プッシュは常に、コンテナにコピーする要素である引数を1つだけ取ります。

2)emplaceは、コンテナにクラスの別のインスタンスを作成します。このインスタンスは、すでにコンテナに追加されています。 emplaceの引数は、引数としてコンテナのクラスのコンストラクターに転送されます。クラスにデフォルトのコンストラクターがある場合、Emplaceには、1つの引数、複数の引数、または引数なしを指定できます。

クラスのコンストラクターが1つの引数を取り、explicitとしてマークされていない場合、Pushを乱用して、クラスの既存のインスタンスの代わりにコンストラクター引数を渡すことができます。しかし、このオプションが存在しないふりをしましょう、それは特にひどいクラスでは特にひどいコードパフォーマンスにつながります。

そのため、クラスの既存のインスタンスのコピーをコンテナに追加する場合は、プッシュを使用します。クラスの新しいインスタンスを最初から作成する場合は、emplaceを使用します。

42
Sam Varshavchik

_vector<X>_がある場合、emplace_back(a, b, c)はベクトル内にXオブジェクトを構築します。

対照的に、Push_back(X(a, b, c))は最初に一時ファイルを作成し、次に一時ファイルをベクターに移動します。

12
fredoverflow