In C ++ 11 emplace_back()
ist im allgemeinen bevorzugt (in Bezug auf der Effizienz) zu , push_back()
da es ermöglicht , in-Place - Konstruktion, aber das ist immer noch der Fall , bei der Verwendung push_back(std::move())
mit einem bereits aufgebauten Objekt?
Wird zum Beispiel emplace_back()
in Fällen wie den folgenden 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)
Gibt es im obigen Beispiel außerdem einen Vorteil, wenn Sie stattdessen Folgendes tun:
myvector.emplace_back(std::move(mystring));
oder ist der Umzug hierher völlig überflüssig oder hat er keine Auswirkungen?
c++11
move-semantics
push-back
emplace
Randalieren
quelle
quelle
myvector.emplace_back(mystring);
kopiert und bewegt sich nicht. Die anderen beiden Züge sollten gleich sein.Antworten:
Mal sehen, was die verschiedenen von Ihnen bereitgestellten Anrufe 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, dh dies entspricht dem Aufrufenpush_back(mystring)
push_back(std::move(mystring))
: Dies ruft die Verschiebungseinfügung auf, die im Fall von std :: string eine direkte Verschiebungskonstruktion 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, nennt es den Verschiebungskonstruktor vonstd::string
, dh es ist eine direkte Verschiebungskonstruktion wie in 2.Mit anderen Worten, wenn es mit einem Argument vom Typ T aufgerufen wird, sei es ein r-Wert oder ein l-Wert
emplace_back
undpush_back
sind äquivalent.Für alle anderen Argumente
emplace_back
gewinnt das Rennen jedoch, zum Beispiel mit einemchar const*
in avector<string>
:emplace_back("foo")
fordertstring::string(char const*)
eine In-Place-Konstruktion.push_back("foo")
Zuerst mussstring::string(char const*)
die implizite Konvertierung aufgerufen werden, die erforderlich ist, um mit der Signatur der Funktion übereinzustimmen, und dann eine Einfügung wie in Fall 2 oben. Daher ist es gleichbedeutend mitpush_back(string("foo"))
quelle
s
kann nur rvalues daß bindet , wie rvalue Referenz definiert werden, aber innerhalb vonfoo
,s
ist ein L - Wert.Der emplace_back ruft eine Liste von rvalue-Referenzen ab und versucht, ein Containerelement direkt an Ort und Stelle zu erstellen. Sie können emplace_back mit allen Typen aufrufen, die von den Containerelementkonstruktoren unterstützt werden. Wenn Sie emplace_back für Parameter aufrufen, die keine rvalue-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 der Zeichenfolge erstellen, da der Compiler nicht wissen konnte, dass der Parameter myvector beweglich ist. Fügen Sie also std :: move ein, um den gewünschten Nutzen zu erzielen. Der push_back sollte für bereits erstellte Elemente genauso funktionieren wie emplace_back.
quelle