Meine Absicht ist Folgendes: Erhalte eine Rvalue-Referenz (d. h. eine Referenz auf ein Objekt, das ich kannibalisieren), entferne einige seiner Ressourcen und gebe dann die anderen Ressourcen zurück. Ich habe diesen Code geschrieben:
%Vor%aber ich bin mir nicht sicher, ob:
std::forward
verwenden? Ich glaube nicht, da dies keine universelle Referenz ist
Ich gehe davon aus, dass der std::vector<int>
-Parameter ein Platzhalter für einen komplexeren Typ ist, wie zB std::vector<Resource>
. Sie können nicht verschieben ein int
und die einzige andere Ressource, die Sie erwerben könnten, wären die Daten des Vektors selbst.
- ist das der richtige Weg, um das zu erreichen, was ich will?
Ja. Wenn Sie std::move
weglassen, wird vec
als Lvalue betrachtet und auf die Rückgabe kopiert.
Sie können dieses Verhalten in diesem Beispiel beobachten:
%Vor%
- Soll ich std :: forward verwenden? Ich glaube nicht, da dies keine universelle Referenz ist
Nein. Es würde nicht weh tun, da std::forward<T>
bedingt (Lvalues nicht umgewandelt werden rvalue Referenzen, Rvalues werden). Es würde jedoch im Grunde dasselbe erreichen wie std::move
mit mehr Typisierung.
Als Faustregel verwenden Sie std::move
mit rvalues und std::forward<T>
mit universellen Referenzen.
ist das der richtige Weg, um zu erreichen, was ich will?
OK, ignorieren wir die Tatsache, dass vector<int>
kein Typ ist, bei dem es sinnvoll ist, nur mit einigen seiner Ressourcen zu fliehen (es gibt nur eine Ressource: die Zuweisung). Ich tue so, als sprichst du von einem Typ, der eigentlich mehrere Ressourcen hat.
Ich würde eine solche Funktion als falsche Darstellung betrachten.
Eine Funktion, die deklariert, dass ein Typ als rvalue-Referenz verwendet wird, sagt etwas sehr wichtig darüber aus, was es mit diesem Wert machen soll. Es wird gesagt, dass es entweder direkt oder indirekt die Bewegung dieses Objekts in ein anderes Objekt dieses Typs ausführt. Es kann es selbst tun, oder es kann jemand anderes anrufen, der es will. Aber das wird passieren, bevor die Funktion zurückkehrt.
Die Idee ist, dass dieser Code genau das bedeutet, was er sagt:
%Vor% Es sieht so aus, als ob value
in SomeFunction
verschoben wird, genauso wie bei SomeType t = std::move(value);
. In beiden Fällen sollte der Status von value
verschoben werden. Andernfalls ist der Code verwirrend.
Eine Funktion, die einen Parameter willkürlich ändern und ihn in einem neuen Zustand belassen möchte, sollte den Parameter als nichtkonstanten lvalue Verweis, nicht als einen r-Wert nehmen. Was genau "modifizieren" bedeutet, hängt von der Funktion ab und was es tun muss. Wenn Sie mit einigen Ressourcen und nicht mit anderen Ressourcen fliehen möchten, können Sie dies mit einer nichtkonstanten Lvalue-Referenz tun. Sie können sogar std::move
von einem Unterobjekt einer nichtkonstanten Lvalue-Referenz eingeben. Aber Sie und Ihre Benutzer sollten verstehen, was der Zustand des Objekts nach dem Funktionsaufruf sein wird.
Wenn Sie einen Parameter mit einer rvalue-Referenz verwenden, ist das eine Abkürzung für "wenn ich zurückkomme, befindet sich dieses Objekt im Status" moveed-from "". Bitte stellen Sie R-Wert-Referenzen nicht nur als nicht-konstante L-Wert-Referenzen falsch dar.
Meine Absicht ist Folgendes: Erhalte eine R-Wert-Referenz (d. h. einen Verweis auf ein Objekt, das ich kannibalisieren), entferne einige seiner Ressourcen und gebe dann die anderen Ressourcen zurück.
Das ist in Ordnung, aber es ist wahrscheinlich besser, entweder:
Entfernen Sie die Ressourcen-Platzhalter vollständig oder
ersetzt die entfernten Ressourcen durch andere Objekte oder
zeigt dem Anrufer an, welche Ressourcen entfernt wurden
Wenn Sie einen dieser Schritte nicht ausführen, kann der Benutzer einen der verschobenen Elemente verwenden, die Sie ausgeschieden haben. Da verschobene Objekte (zumindest in der STL) einen "gültigen, aber undefinierten" Zustand haben, wird die Verwendung dieser kannibalisierten Objekte undefinierte Ergebnisse haben.
Das willst du nicht.
ist das der richtige Weg, um zu erreichen, was ich will?
Es scheint in Ordnung
Soll ich std :: forward verwenden? Ich glaube nicht, da dies keine universelle Referenz ist
Nein, du solltest nicht. Ihre Argumentation ist richtig.
Hinweis: 'Den Benutzern anzeigen, welche Ressourcen entfernt wurden' hat ein Modell in der Standardbibliothek. Sehen Sie sich std::remove_if
an - es verschiebt tatsächlich die 'entfernten' Elemente an das Ende der Sequenz und gibt einen Iterator zurück, der end
der verbleibenden Elemente und den Anfang der 'entfernten' Elemente markiert.
Hier ist eine Möglichkeit, wie ich das Problem angehen könnte.
Ziel: tue etwas mit allen Strings, die lexikalisch größer als "ccc" in einem Vektor sind, lass den Rest in der ursprünglichen Reihenfolge im Vektor.
%Vor%erwartete Ausgabe:
%Vor%Es wird in den meisten Fällen effizientere Lösungen geben, aber diese vermeidet Speicherzuweisungen.
Tags und Links c++