K
DocShoe schrieb:
Weil ich kaum C++11 mache und die neuen Referenztypen nicht ganz verstanden habe
Test&& ist nichts Magisches, nur ein Referenz-Typ. Dass man von einer Funktion keine Referenz auf funktionslokales Objekte zurück gibt, weil es ja nicht mehr existieren würde nachdem die Ausführung mit der Funktion fertig ist, gilt für alle Referenzen.
Der Unterschied zwischen int& und int&& liegt nur darin, wie sich diese Referenzen initialisieren lassen und bei der Überladungsauflösung:
void lvalue(int&);
void rvalue(int&&);
void test_overload(const int&); // #1
void test_overload(int&&); // #2
int main() {
int lve = 32;
lvalue(lve); // OK, lve ist ein lvalue Ausdruck
lvalue(42); // Illegal, kompiliert nicht
rvalue(lve); // Illegal, kompiliert nicht
rvalue(42); // OK, 42 ist ein rvalue Ausdruck
test_overload(lve); // OK. Viable: { #1 }, resolve to #1
test_overload(42); // OK. Viable: { #1, #2 }, resolve to #2
test_overload(std::move(lve)); // OK. Viable: { #1, #2 }, resolve to #2
}
In den letzten beiden Fällen sind beide Überladungen "viable" (weil bei #1 noch ein const dabei steht) aber die Überladung wird zugunsten von #2 aufgelöst. #2 ist ein besserer Match.
Diese Art der Überladung findet üblicherweise bei Konstruktoren statt (Copy-Constructor + Move-Constructor). Was bei einem Move dann genau passiert, das definiert ja dann der Klassen-Autor über den Move-Konstruktor selbst.
Die Idee ist nur, dass man in einer Funktion, die ein Ding&& entgegen nimmt, mit dem Ding alles machen kann, ohne dass sich der Aufrufer beschweren kann; denn entweder bezieht sich die Referenz auf ein temporäres Objekt, auf das kein anderer mehr Zugriff hat, oder der Aufrufer hat explizit per std::move gesagt, dass er kein Interesse mehr an dem aktuellen Zustand des Objektes hat.