Nach dem, was ich gelesen und gesehen habe, können Sie keinen Ausdruck, der ein R-Wert ist, an einen L-Wert-Bezug binden. Was ich jedoch gesehen habe ist, dass Sie einen rvalue an eine rvalue-Referenz binden können und da eine benannte rvalue-Referenz inhärent ein lvalue ist, können Sie sie an eine lvalue-Referenz binden. Was ist der Grund dafür, einen Rvalue nicht an eine Lvalue-Referenz zu binden? Ist es zu Optimierungszwecken?
Nehmen Sie dieses Beispiel:
%Vor%Es ist eine Grundregel von C ++ und es verhindert Fehler:
%Vor%"Rvalue references" (eine Menge von Typen; nicht zu verwechseln mit tatsächlichen rvalues ) wurden zumindest teilweise erstellt, so dass Sie dies tun können, wenn Sie das tun möchte wirklich:
%Vor%In den vorherigen Beispielen binde ich (oder versuche, Objekte zu binden), auf die "referenziert" wird, durch einen rvalue-Ausdruck an eine Referenz.
Nun werde ich das Objekt, das mit einem lvalue-Ausdruck benannt ist, an eine Referenz binden:
%Vor% Und um sicherzustellen, dass Sie wirklich eine rvalue-Referenz von einem lvalue-Ausdruck erhalten möchten, führen Sie den unglaublich schlecht benannten std::move
:
Diese späteren Regeln kamen viel, viel später als die ursprüngliche Grundregel, die zweifellos viele Fehler in den letzten zwanzig Jahren verhindert hat.
Beachten Sie, dass Visual Studio in der Vergangenheit T& x = bar()
akzeptiert hat, wobei T
ein benutzerdefinierter Typ ist. geh Figur.
Was ist der Grund dafür, dass kein rvalue an eine lvalue-Referenz gebunden werden darf?
Keine Antwort auf diese Frage kann ohne einen Verweis auf die unschätzbare Quelle, Design und Entwicklung von C ++ von Bjarne Stroustrup, vollständig sein .
In Abschnitt 3.7 schreibt Bjarne:
Ich habe jedoch einen schwerwiegenden Fehler gemacht, indem ich eine nicht
%Vor%const
-Referenz zuließ durch einen Nicht-L-Wert initialisiert werden. Zum Beispiel:Wegen des Unterschieds im Typ kann
int&
nicht auf diedouble
wurde übergeben, so dass ein temporäres generiert wurde, um einint
zu halten Initialisiert durch den Wert vonss
. Daher hatincr()
das temporäre geändert und Das Ergebnis wurde nicht in die aufrufende Funktion zurückgespiegelt.
Ich empfehle Design und Entwicklung von C ++ , um viele der "Warum-Fragen" zu verstehen, die man besonders haben könnte in Bezug auf die Regeln, die vor dem C ++ 98-Standard festgelegt wurden. Es ist eine informative und faszinierende Geschichte der Sprache.
Wenn Sie foo(1)
aufrufen, wird ein temporäres int
gleich 1
erstellt und int&& a
ist daran gebunden. Sie können es frei ändern. Genauso können Sie int&& a = 1;
schreiben. a
selbst ist ein Lvalue, daher können Sie eine lvalue-Referenz an sie binden.
Sie können einen großartigen Artikel Universalreferenzen von Scott Meyers lesen Das erklärt Rvalue und Lvalue Referenzen im Detail.