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?
Mal sehen, was die verschiedenen Anrufe, die Sie bereitgestellt haben, bewirken:
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)
.
Push_back(std::move(mystring))
: Dies ruft die Verschiebeeinfügung auf, die im Fall von std :: string eine In-Place-Verschiebe-Konstruktion ist.
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>
:
emplace_back("foo")
ruft string::string(char const*)
für die In-Place-Konstruktion auf.
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"))
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.