Nehmen wir zwei Strukturen / Klassen
%Vor%Und als
%Vor%Die Ausgabe ist
%Vor%Wir wissen, dass Mitglieder von Rvalues selbst Rvalues sind. Deshalb wird mit a1 der Move-Konstruktor aufgerufen. Warum wird der Kopierkonstruktor im Fall von a2 aufgerufen? Wir geben einen Rvalue von einer Funktion zurück.
Um es anders auszudrücken: std :: verschiebt Umwandlungen in einen rvalue. Aber als Mitglied eines R-Wertes ist c bereits ein R-Wert. Warum gibt es einen Unterschied zwischen dem Verhalten mit a2 und a3?
Gute Frage. Die langweilige Antwort ist, dass es in der C ++ - Spezifikation keine Regel gibt, die besagt, dass die Rückgabe eines Members aus einem sterbenden Objekt wie diesem das Objekt automatisch verschiebt.
Vielleicht interessiert es Sie, was man rvalue als Referenz zu diesem nennt. Lassen Sie uns &&
und &
so überladen, dass Sie das von Ihnen erwartete Verhalten manuell implementieren können:
Jetzt
%Vor%druckt
%Vor%Cool, aber ziemlich selten.
Verwandte:
Wir wissen, dass Mitglieder von Rvalues selbst Rvalues sind.
Ja, das ist wahr, wie es heißt [expr.ref] /4.2 ( Betonung meiner):
Wenn E2 ein nicht statisches Datenelement ist und der Typ von E1 "cq1 vq1 X" ist und der Typ von E2 "cq2 vq2 T" ist, bezeichnet der Ausdruck das benannte Element des durch den ersten Ausdruck bezeichneten Objekts . Wenn E1 ein Lvalue ist, dann ist E1.E2 ein Lvalue; sonst ist E1.E2 ein xvalue. Sei die Schreibweise vq12 für die "union" von vq1 und vq2; Das heißt, wenn vq1 oder vq2 flüchtig ist, ist vq12 flüchtig. In ähnlicher Weise soll die Schreibweise cq12 für die "Vereinigung" von cq1 und cq2 stehen; Das heißt, wenn cq1 oder cq2 const ist, dann ist cq12 const. Wenn E2 als änderbares Mitglied deklariert ist, ist der Typ von E1.E2 "vq12 T". Wenn E2 nicht als änderbares Mitglied deklariert ist, ist der Typ von E1.E2 "cq12 vq12 T".
Und auch von [expr.ref] /4.5 :
Wenn E2 ein Member-Enumerator ist und der Typ von E2 T ist, ist der Ausdruck E1.E2 ein Pr-Wert. Der Typ von E1.E2 ist T.
So weit, so gut. Sie können nur dann einen lvalue erhalten, wenn E1
ein lvalue selbst ist, andernfalls ein xvalue oder ein prvalue.
Aber als Mitglied eines rvalue, c, ist bereits ein rvalue.
Hier liegen Ihre Annahmen falsch.
Aus [class.this] / 1 (Hervorhebung von mir)
Im Hauptteil einer nicht statischen (9.3) Elementfunktion ist das Schlüsselwort dies ein Prvalue-Ausdruck, dessen Wert ist die Adresse des Objekts, für das die Funktion aufgerufen wird. Der Typ in einer Memberfunktion von Eine Klasse X ist X * .
this
ist ein Prvalue vom Typ X*
, und dereferenziert einen Zeiger vom Typ X
ergibt einen lvalue vom Typ X
.
Da der Zugriff auf ein Element innerhalb einer Elementfunktion äquivalent zu (*this).m
ist, wird auf m
über einen Lvalue vom Typ X
zugegriffen.
Ihr Code entspricht also:
%Vor% Da this
immer vom selben Typ ist, wird der Ausdruck c
in einer Member-Funktion auch bei Verwendung eines ref-Qualifikationsmerkmals immer ein lvalue sein:
Tags und Links c++ move-semantics rvalue