Warum können Sie einen rvalue indirekt an eine lvalue-Referenz binden, aber nicht direkt?

8

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%     
edaniels 14.10.2014, 20:15
quelle

3 Antworten

9

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 :

ein %Vor%

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.

    
Lightness Races in Orbit 14.10.2014, 22:14
quelle
6
  

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 const -Referenz zuließ   durch einen Nicht-L-Wert initialisiert werden. Zum Beispiel:

%Vor%      

Wegen des Unterschieds im Typ kann int& nicht auf die    double wurde übergeben, so dass ein temporäres generiert wurde, um ein int zu halten   Initialisiert durch den Wert von ss . Daher hat incr() 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.

    
Howard Hinnant 14.10.2014 23:37
quelle
0

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.

    
Anton Savin 14.10.2014 20:38
quelle

Tags und Links