7 Stimmen

Unterschied zwischen der Rückgabe einer `const`-Referenz und einer Rvalue-Referenz

Wenn ich mich nicht irre, denke ich, dass sowohl eine const-Referenz als auch eine Rvalue-Referenz an eine Rvalue binden können. Gibt es einen praktischen Unterschied zwischen einer Funktion, die die erste zurückgibt, und einer Funktion, die letztere zurückgibt?

BEARBEITEN. Ich kann die erste nicht ändern, aber warum wäre ich daran interessiert, eine Rvalue zu modifizieren? Macht das Sinn?

16voto

Joseph Mansfield Punkte 104275

Eine const lvalue-Referenz kann sich an alles binden. Eine rvalue-Referenz kann sich nur an nicht-const rvalues binden.

            non-const lvalue   const lvalue   non-const rvalue   const rvalue
const T&    yes                yes            yes                yes
T&&         no                 no             yes                no

Wie Sie sehen können, sind sie sehr unterschiedlich.

Zusätzlich, wenn ein Funktionsaufruf eine lvalue-Referenz zurückgibt, ist dieser Ausdruck eine lvalue, aber wenn ein Funktionsaufruf eine rvalue-Referenz auf ein Objekt zurückgibt, ist dieser Ausdruck ein xvalue.

Ein Funktionsaufruf ist eine lvalue, wenn der Ergebnistyp ein lvalue-Referenztyp oder eine rvalue-Referenz auf Funktionstyp ist, ein xvalue, wenn der Ergebnistyp ein rvalue-Referenz auf Objekttyp ist, und ein prvalue, wenn dies nicht der Fall ist.

Wenn Sie ein rvalue ändern möchten - genau das sind die Bewegungssemantiken. Betrachten Sie den folgenden Funktionsaufruf:

void func(std::string);

func(std::string("Hallo"));

Der Ausdruck std::string("Hallo") ist eine rvalue, die ein temporäres Objekt erstellt. Beim Initialisieren des Parameters std::string mit dieser rvalue wird der Konstruktor gewählt, der eine rvalue-Referenz akzeptiert - der Bewegungskonstruktor. Dieser Konstruktor stiehlt dann Dinge von der rvalue, was typischerweise viel schneller ist als eine vollständige Kopie. Wir können von ihm stehlen, weil wir wissen, dass es temporär ist.

Bezüglich des Rückgabetyps von const lvalue-Referenzen oder rvalue-Referenzen:

  • Das Zurückgeben eines const lvalue-Verweises wird am häufigsten verwendet, wenn Sie Zugriff auf das Lesen eines "internen" Objekts geben möchten (vielleicht ein Element einer Klasse), aber Personen nicht erlauben möchten, es zu ändern.

  • Das Zurückgeben einer rvalue-Referenz wird am häufigsten verwendet (sehr selten), wenn Sie möchten, dass der aufrufende Code von einem "internen" Objekt (vielleicht ein Element einer Klasse) verschoben werden kann. Anstatt also von einem temporären zurückgegebenen Objekt zu verschieben (wie bei der Rückgabe durch Wert), verschieben sie tatsächlich das interne Objekt.

    Dies könnte auch mit einem nicht-const lvalue-Verweis erreicht werden, aber dann müssten sie es explizit mit std::move verschieben.

Es ist also sehr unwahrscheinlich, dass Sie eine rvalue-Referenz zurückgeben müssen.

Nicht dass std::forward einen Rückgabetyp hat, der wie T&& aussieht. Dies ist jedoch irreführend, da es je nach Typ von T eine rvalue-Referenz sein kann oder nicht. Siehe universal references.

4voto

Gibt es einen praktischen Unterschied zwischen einer Funktion, die ersteres zurückgibt, und einer Funktion, die letzteres zurückgibt?

Die Frage scheint nicht wohlgeformt zu sein. Eine Funktion, die eine konstante Lvalue-Referenz zurückgibt, bietet nur Zugriff auf ein Objekt zum Lesen, während eine Funktion, die eine Rvalue-Referenz zurückgibt, Zugriff zum Verschieben bietet, was bedeutet, dass der Aufrufer den Inhalt des referenzierten Objekts nehmen und ihn in ein anderes Objekt verschieben kann. Sie sind in keiner Weise vergleichbar.

In beiden Fällen müssen die Referenzen auf ein Objekt zeigen, dessen Lebensdauer über das Ende der Funktion hinausgeht, die es zurückgibt, da sonst der Aufrufer beim Verwenden dieser Referenz auf undefiniertes Verhalten stößt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X