Ich habe das hier gesehen: Move Constructor ruft den Move Constructor der Basisklasse auf
Könnte jemand erklären:
- der Unterschied zwischen
std::move
undstd::forward
, vorzugsweise mit einigen Codebeispielen? - Wie man leicht darüber nachdenkt und wann man welche benutzt
c++
c++11
perfect-forwarding
aCuria
quelle
quelle
move
wenn Sie wollen bewegen Wert, undforward
wenn Sie möchten , perfekte Weiterleitung. Dies ist hier keine Raketenwissenschaft;)Antworten:
std::move
Nimmt ein Objekt und ermöglicht es Ihnen, es als temporär (einen Wert) zu behandeln. Obwohl dies keine semantische Anforderung ist, macht eine Funktion, die einen Verweis auf einen r-Wert akzeptiert, diesen normalerweise ungültig. Wenn Sie sehenstd::move
, wird angezeigt, dass der Wert des Objekts danach nicht mehr verwendet werden soll. Sie können jedoch einen neuen Wert zuweisen und ihn weiterhin verwenden.std::forward
hat einen einzigen Anwendungsfall: Um einen Funktionsparameter mit Vorlagen (innerhalb der Funktion) in die Wertekategorie (lvalue oder rvalue) umzuwandeln, die der Aufrufer verwendet hat, um ihn zu übergeben. Auf diese Weise können rvalue-Argumente als rvalues und lvalues als lvalues weitergegeben werden, ein Schema, das als "perfekte Weiterleitung" bezeichnet wird.Zur Veranschaulichung :
Wie Howard erwähnt, gibt es auch Ähnlichkeiten, da diese beiden Funktionen einfach in den Referenztyp umgewandelt werden. Außerhalb dieser speziellen Anwendungsfälle (die 99,9% des Nutzens von rvalue-Referenz-Casts abdecken) sollten Sie diese jedoch
static_cast
direkt verwenden und eine gute Erklärung für Ihre Aktivitäten schreiben.quelle
std::forward
der einzige Anwendungsfall die perfekte Weiterleitung von Funktionsargumenten ist. Ich bin auf Situationen gestoßen, in denen ich andere Dinge wie Objektmitglieder perfekt weiterleiten möchte.Beides
std::forward
undstd::move
sind nichts als Abgüsse.Das Obige wandelt den l-Wert-Ausdruck
x
vom Typ X in einen r-Wert-Ausdruck vom Typ X um (genauer gesagt einen x-Wert).move
kann auch einen rwert akzeptieren:und in diesem Fall handelt es sich um eine Identitätsfunktion: Nimmt einen r-Wert vom Typ X und gibt einen r-Wert vom Typ X zurück.
Mit
std::forward
können Sie das Ziel bis zu einem gewissen Grad auswählen:Wandelt den l-Wert-Ausdruck
x
vom Typ X in einen Ausdruck vom Typ Y um. Es gibt Einschränkungen, was Y sein kann.Y kann eine zugängliche Basis von X sein oder ein Verweis auf eine Basis von X. Y kann X sein oder ein Verweis auf X. Man kann Lebenslauf-Qualifizierer nicht mit wegwerfen
forward
, aber man kann Lebenslauf-Qualifizierer hinzufügen. Y kann kein Typ sein, der lediglich von X konvertierbar ist, außer über eine zugängliche Basiskonvertierung.Wenn Y eine lWertreferenz ist, ist das Ergebnis ein lWertausdruck. Wenn Y keine l-Wert-Referenz ist, ist das Ergebnis ein r-Wert-Ausdruck (genauer gesagt x-Wert).
forward
kann ein rvalue-Argument nur annehmen, wenn Y keine lvalue-Referenz ist. Das heißt, Sie können keinen Wert in einen Wert umwandeln. Dies ist aus Sicherheitsgründen so, da dies häufig zu baumelnden Referenzen führt. Aber es ist in Ordnung und erlaubt, einen Wert in einen Wert umzuwandeln.Wenn Sie versuchen, Y für etwas anzugeben, das nicht zulässig ist, wird der Fehler zur Kompilierungszeit und nicht zur Laufzeit abgefangen.
quelle
std::forward
, nachdem ich ein Objekt mithilfe von perfekt an eine Funktion weitergeleitet habe ? Mir ist bewusst, dass es sich im Falle von umstd::move
ein undefiniertes Verhalten handelt.move
: stackoverflow.com/a/7028318/576911 Fürforward
, wenn Sie in einem L - Wert, Ihre API übergeben sollten reagieren , als ob es einen L - Wert erhält. Normalerweise bedeutet dies, dass der Wert nicht geändert wird. Wenn es sich jedoch um einen nicht konstanten Wert handelt, hat Ihre API ihn möglicherweise geändert. Wenn Sie einen r-Wert übergeben, bedeutet dies normalerweise, dass Ihre API möglicherweise von diesem Wert verschoben wurde und daher stackoverflow.com/a/7028318/576911 angewendet wird .std::forward
wird verwendet, um einen Parameter genau so weiterzuleiten , wie er an eine Funktion übergeben wurde. Genau wie hier gezeigt:Wann sollte std :: forward verwendet werden, um Argumente weiterzuleiten?
Die Verwendung
std::move
bietet ein Objekt als r-Wert an, um möglicherweise einem Verschiebungskonstruktor oder einer Funktion zu entsprechen, die r-Werte akzeptiert. Es macht dasstd::move(x)
auch dann, wennx
es kein Wert für sich ist.quelle