1. ホーム
  2. c++11

[解決済み] C++11のpush_back()とstd::moveとemplace_back()の構築済みオブジェクトに対する効率性

2023-01-29 08:55:31

疑問点

C++11では emplace_back() は一般に(効率の点から)次のように好まれます。 push_back() の方が、インプレース構造が可能であるため、(効率の点から)好ましいとされています。 を使用する場合でもそうなのでしょうか? push_back(std::move()) を既に構築されたオブジェクトと一緒に使用する場合でもそうですか?

例えば emplace_back() は、次のようなケースでも好まれるのでしょうか?

std::string mystring("hello world");
std::vector<std::string> myvector;

myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
// (of course assuming we don't care about using the value of mystring after)

さらに、上記の例で、代わりにするメリットはありますか?

myvector.emplace_back(std::move(mystring));

それとも、ここでの動きは全く冗長で、何の効果もないのでしょうか?

どのように解決するのですか?

提供された異なるコールが何をするのか見てみましょう。

  1. emplace_back(mystring) : これは、あなたが提供した引数で新しい要素をインプレースで構築するものです。lvalueを与えたので、このインプレース構築は実際にはコピー構築です、つまり、これは push_back(mystring)

  2. push_back(std::move(mystring)) : これは移動挿入を呼び出すもので、その場合 std::string の場合はインプレース移動構成です。

  3. emplace_back(std::move(mystring)) : これはまた、あなたが提供した引数によるインプレース構築です。この引数は rvalue であるので、これは std::string のmove-constructorを呼び出す、つまり2のようなin-place move-constructionです。

言い換えれば、T型の1つの引数で呼ばれた場合、それがrvalueであれlvalueであれ。 emplace_back となり push_back は等価です。

しかし、他の引数(複数可)に対しては emplace_back が勝り、例えば char const* の中に vector<string> :

  1. emplace_back("foo") コール std::string(char const*) を呼び出し、その場で構築する。

  2. push_back("foo") を最初に呼び出す必要があります。 std::string(char const*) を呼び出して関数のシグネチャと一致させる暗黙の変換を行い、 その後、上記のケース 2.のように移動挿入を行います。したがって、これは次のように等価です。 push_back(string("foo"))