Rvalue Referenzen werden implizit rvalues (genauer gesagt zu XValues) umgewandelt, wie eine der Standardumwandlungen (Kapitel 4 des C++ Standard):
Die Wirkung jeder impliziten Umwandlung ist das gleiche wie die Durchführung die entsprechende Deklaration und Initialisierung und dann die temporäre Variable als Ergebnis der Konvertierung. Das Ergebnis ist ein lvalue wenn T eine L-Wert oder eine Referenztyp rvalue Bezugnahme auf Funktionstyp (8.3.2) ist, ein xValue wenn T eine rvalue Referenz Typen und ein prvalue sonst
einzuwenden
Rvalues (einschließlich XValues) an const
lvalue Referenzen gebunden werden, so dass man eine temporäre auf eine Funktion mit einem solchen Parameter übergeben werden kann:
void foo(const bar &a);
// ...
foo(bar());
(A vorübergehend ist ein R-Wert, in diesem Fall t Das Ergebnis von bar()
ist ein rvalue). Es gibt keinen Grund nicht dies zu erlauben, da das temporäre immer so lange lebt wie der enthaltene Ausdruck - in diesem Fall der Funktionsaufruf - und so wird es keinen baumelnden Verweis innerhalb foo
erstellen.
Das bedeutet, dass es immer möglich ist, die Signatur einer Funktion fun(bar)
an fun(const bar &)
anzupassen - und natürlich die Implementierung entsprechend zu ändern! - da temporäre Argumente immer noch akzeptiert werden und die Semantik aus Sicht des Aufrufers gleich sein sollte; const
bedeutet, dass das Objekt nicht geändert wird, was auch der Fall ist, wenn es durch Kopieren übergeben wird.
Nicht-const
Referenzen sind nicht erlaubt; Ein praktischer Grund ist, weil sie implizieren, dass der Wert in einer sinnvollen Weise geändert werden sollte, und wenn der Wert ein vorübergehender Wert ist, würde dies verloren gehen. Sie können jedoch einen R-Wert in einen L-Wert konvertieren, wenn Sie dies wirklich wollen, mit einigen Einschränkungen, wie in this answer zu einer anderen Frage beschrieben.
Die Möglichkeit, einen Rvalue an eine const
lvalue-Referenz zu binden, abgesehen von der temporären Übergabe von Argumenten, eignet sich auch für Fälle, in denen der genaue Parametertyp nicht bekannt ist, Sie aber Bewegungssemantik zulassen möchten . Nehmen wir an, dass ich eine Funktion nenne, die als foo2(const bar &)
oder foo2(bar)
und die im ersten Fall definiert werden kann oder nicht eine Überlastung kann foo2(bar &&)
, und ich möchte, damit bewegen Semantik zu verwenden, wenn möglich (unter der Annahme, dass eine foo2(bar &&)
Überlastung verwenden Verschieben Sie die Semantik in ihrer Implementierung); Ich kann sicher std::move
verwenden, um einen Rvalue zu erstellen, da es in jedem Fall gilt. Dieses Beispiel mag ein wenig künstlich wirken, aber es ist eine Sache, die beim Schreiben von Templates ziemlich oft auftauchen kann. In Code:
bar bb = bar();
foo2(std::move(bb));
// above is legal if foo2 is declared as either:
// foo2(bar)
// foo2(const bar &)
// and in latter case calls overload foo2(bar &&) if it is defined.
Im Fall von anderen rvalue-zu-L-Wert-Referenz Zuweisungen eines vorübergehende Beteiligung wird die Lebensdauer der temporären derjenigen der Referenz erweitert, so dass sie baumelnden Referenzen nicht einmal in Kontexten erstellt andere als Parameterübergabe:
const bar &b = bar(); // temporary lifetime is extended
In dem oben die bar
Objekt nicht zerstört werden, bis b
die Referenz den Gültigkeitsbereich verlässt.
Ich finde diese Frage ein wenig schwer zu parsen, weil Sie die Terminologie falsch herum verwenden: In 'T & t = u;', sagen wir, dass "(die Referenz)" t 'an den Wert 'u bindet "." Beachten Sie außerdem, dass Referenzen immer an * Werte * gebunden sind; Eine Referenz bindet nicht an eine andere Referenz. Referenztypen sind immer mit * Variablen * (oder Funktionen) verbunden, niemals mit Ausdrücken. In der üblichen Verwendung der Terminologie könnte die Frage lauten: "Warum binden sich lvalue-Referenzen an rvalues?", Was eine gute Frage ist (mit einer einfachen Antwort). –
@KerrekSB Meine schlechte, ich habe die Frage bearbeitet, um (hoffentlich) die richtige Terminologie zu verwenden – Dean
es [kann nicht kompilieren] (http://coliru.stacked-crooked.com/a/3aca61d34a714765) ohne 'const' –