Quote:
Originally Posted by Padmak
Sorry an den TE dass ich das hier ein bisschen kapere, aber das klingt nun doch ziemlich interessant. Hast du irgendwas dazu, dass aus der eigentlichen std::string(void)-Funktion eine std::string&&(void)-Funktion wird?
|
Ich glaube da habe ich mich falsch ausgedrückt. An der Funktionssignatur wird nichts verändert.
Quote:
Originally Posted by Padmak
Ich vermute du spielst auf RVO an, stimmt das? Und wenn ja, ist irgendwo garantiert wie das funktioniert?
|
Nein tue ich nicht. RVO findet innerhalb der Funktion statt (dh. in der Funktion die etwas zurück gibt). Ja es ist garantiert wie und wann das funktioniert.
Also. Grundsätzlich ist eine rvalue Referenz auch eine Referenz. Das heißt, dass sowas:
Code:
MyClass&& get()
{
MyClass m;
return std::move(m);
}
eine Referenz auf ein nicht mehr existierendes Objekt (m) zurück gibt (undefined behaviour). Deswegen wird der Compiler die Signatur auch nicht zu std::string&& get() ändern und man selber sollte es auch nicht (außer man weiß wirklich was man macht; die stl macht das bei dem operator* vom iterator z.B.). Dafür ist ja schließlich RVO/NRVO da.
Code:
std::string getMyVal()
{
std::string ret = "......";
return ret; // HIER findet NRVO statt, da ret nicht mehr genutzt wird darf der compiler das.
}
Aber RVO/NRVO hat nicht wirklich was, mit dem was ich gesagt habe zu tun. Es kann halt nur in der Funktion, die etwas zurück gibt, statt finden, aber mir ging es eher darum, welche Funktion aufgerufen wird, also um Overload Resolution.
Ich habe mich da definitiv falsch ausgedrückt. Der Typ von dem Rückgabewert ist und bleibt MyClass bzw. std::string.
Code:
MyClass getMyClass(){...}
void myFunc(const MyClass& m){...} // 1
void myFunc(MyClass&& m){...}//2
myFunc(getMyClass()); // 3
Bei Zeile 3 muss jetzt zuerst getMyClass() aufgerufen werden. Dann hat der Compiler da dieses Objekt vom Typ MyClass rumliegen und das ist defintiv temporär. RValue (=temporäre) Objekte können an lvalue und rvalue Referenzen gebunden werden, aber eine rvalue Referenz ist die bessere Übereinstimmung. Das heißt, wenn der Compiler jetzt die Funktion sucht, die aufgerufen werden soll, hätte man mit der 2. Funktionssignatur die bessere Übereinstimmung. Wenn die 2. Funktionsignatur nicht existiert, weil der Programmierer sie nicht geschrieben hat, dann wird die 1. Funktion aufgerufen.