Kann nur einige Ressourcen eines rvalue ref

8

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:

  1. ist das der richtige Weg, um das zu erreichen, was ich will?
  2. Soll ich std::forward verwenden? Ich glaube nicht, da dies keine universelle Referenz ist
Dean 12.05.2016, 17:01
quelle

3 Antworten

2

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.

  
  1. ist das der richtige Weg, um das zu erreichen, was ich will?
  2.   

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%
  
  1. 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.

    
user2296177 12.05.2016, 17:08
quelle
5
  

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.

    
Nicol Bolas 12.05.2016 17:21
quelle
3
  

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.

    
Richard Hodges 12.05.2016 17:12
quelle

Tags und Links