wake-up-neo.com

Effizienz von C ++ 11 Push_back () mit std :: move versus emplace_back () für bereits erstellte Objekte

In C++ 11 wird emplace_back() im Allgemeinen (im Hinblick auf die Effizienz) gegenüber Push_back() bevorzugt, da es eine direkte Konstruktion ermöglicht , ist dies aber immer noch Ist es der Fall, wenn Push_back(std::move()) mit einem bereits erstellten Objekt verwendet wird?

Wird emplace_back() beispielsweise in folgenden Fällen immer noch bevorzugt?

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)

Hat das obige Beispiel außerdem den Vorteil, stattdessen Folgendes zu tun:

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

oder ist der umzug hier gänzlich überflüssig oder wirkungslos?

76
Riot

Mal sehen, was die verschiedenen Anrufe, die Sie bereitgestellt haben, bewirken:

  1. emplace_back(mystring): Dies ist eine direkte Konstruktion des neuen Elements mit dem von Ihnen angegebenen Argument. Da Sie einen Wert angegeben haben, handelt es sich bei dieser In-Place-Konstruktion tatsächlich um eine Kopierkonstruktion, d. H., Dies entspricht dem Aufrufen von Push_back(mystring).

  2. Push_back(std::move(mystring)): Dies ruft die Verschiebeeinfügung auf, die im Fall von std :: string eine In-Place-Verschiebe-Konstruktion ist.

  3. emplace_back(std::move(mystring)): Dies ist wieder eine In-Place-Konstruktion mit den von Ihnen angegebenen Argumenten. Da dieses Argument ein R-Wert ist, ruft es den Verschiebungskonstruktor von std::string Auf, d. H. Es ist eine In-Place-Verschiebungskonstruktion wie in 2.

Mit anderen Worten, wenn mit einem Argument vom Typ T aufgerufen wird, sei es ein Wert oder ein Wert, sind emplace_back Und Push_back Äquivalent.

Bei allen anderen Argumenten gewinnt jedoch emplace_back Das Rennen, zum Beispiel mit einem char const* In einem vector<string>:

  1. emplace_back("foo") ruft string::string(char const*) für die In-Place-Konstruktion auf.

  2. Push_back("foo") muss zuerst string::string(char const*) aufrufen, damit die implizite Konvertierung mit der Signatur der Funktion übereinstimmt, und dann ein Move-Insert wie in Fall 2 oben. Daher ist es äquivalent zu Push_back(string("foo"))

104
Arne Mertz

Das emplace_back ruft eine Liste der r-Wert-Referenzen ab und versucht, ein Containerelement direkt an Ort und Stelle zu erstellen. Sie können emplace_back mit allen Typen aufrufen, die die Containerelementkonstruktoren unterstützen. Wenn Sie emplace_back für Parameter aufrufen, die keine rWert-Referenzen sind, wird auf normale Referenzen zurückgegriffen, und zumindest der Kopierkonstruktor wird aufgerufen, wenn der Parameter und die Containerelemente vom gleichen Typ sind. In Ihrem Fall sollte 'myvector.emplace_back (mystring)' eine Kopie des Strings erstellen, da der Compiler nicht wissen konnte, dass der Parameter myvector verschiebbar ist. Fügen Sie also den std :: move ein, der Ihnen den gewünschten Nutzen bringt. Das Push_back sollte genauso funktionieren wie das emplace_back für bereits erstellte Elemente.

1
Tunichtgut