2016-12-03 5 views
7

Lassen Sie uns sagen, dass wir diese SituationWird RVO in dieser Situation angewendet?

std::string v_1() 
{ 
    return "name"; 
} 
std::string test = v_1(); 

Ist RVO hier angewendet haben? Ich denke, dass die Antwort nein ist, denn die Regeln für die Anwendung von RVO lautet: "Wenn eine Funktion einen Klassentyp nach Wert zurückgibt und der Ausdruck der return-Anweisung der Name eines nichtflüchtigen Objekts mit automatischer Speicherdauer ist, was isn 't der Funktionsparameter oder ein Parameter der Fangklausel und , der den gleichen Typ (ohne Berücksichtigung der CV-Qualifikation der obersten Ebene) als Rückgabetyp der Funktion hat, dann entfällt Kopieren/Verschieben " Und in dieser Situation Das zurückgegebene Objekt hat nicht den gleichen Typ des Rückgabetyps der Funktion, aber ich bin nicht 100%, dass RVO hier nicht angewendet wird.

Vielen Dank.

PS. In diesem Vortrag https://www.youtube.com/watch?v=AKtHxKJRwp4 (Minute 40, Sekunde 18) Stephan, von Microsoft, spricht über eine Situation, in der RVO nicht angewendet werden kann, da der Rückgabetyp der Funktion anders ist als der Typ des zurückgegebenen Objekts (in seinem Beispiel ein Tupel vs ein Paar)). Ich denke, dass hier das gleiche Prinzip gilt.

+3

Es ist meist gleichbedeutend mit 'return std :: string (" name ")' ... – Jarod42

+0

Was zurückgegeben wird, ist * nicht * die 'const char *' ... – user268396

+0

@ user268396 Sie haben Recht, aber in den meisten cases (auch hier) wird implizit in eins konvertiert, bevor es in string konvertiert wird ... :) –

Antwort

5

Ich denke, dass Sie NRVO mit RVO verwirren.

  • NRVO - Named Rückgabewert Optimierung
  • RVO - (unbenannt) Rückgabewert Optimierung

NRVO beinhaltet eine benannte Variable während RVO unbenannte Provisorien beinhaltet, die in der return Anweisung aufgebaut sind.

Das Beispiel auf dem Video ist NRVO wo die Objekt mit dem Namen offensichtlich nicht auf den Anrufer Stapel aufgebaut werden kann, wenn die Typen unterschiedlich sind, weil es in der Funktion des Stapel und einem anderen Objekt eines Typs vorhanden sein muss Objekt des anderen Typs auf dem Stapel des Aufrufers.

Ihr Beispiel ist RVO, in dem Sie kein vordefiniertes benanntes Objekt verwenden. In Ihrem Code sind Sie Konstruieren ein temporäre Objekt als Rückgabewert. Da es sich um eine temporäre handelt, gilt die von Ihnen angegebene Regel nicht.

Nach dem C++11 Standard sehe ich keinen Grund, warum RVO nicht auftreten kann:

12,8 Kopieren und Verschieben von Klassenobjekten [ class.copy ] ... ...

- wenn ein temporäres Klassenobjekt nicht boun ist d zu einer Referenz (12.2) würde kopiert/verschoben auf ein Klassenobjekt mit dem gleichen cv-unqualifizierten Typ, das Kopieren/Verschieben Vorgang kann durch Konstruieren des temporäre Objekts direkt in das Ziel der weggelassen Kopie entfallen/bewegen

Durch die Rückgabe eines char array wird eine temporäre std::string erstellt und , die ist, was zum Anrufer zurückgegeben wird.

3

NRVO und RVO sind verschiedene Fälle von Elision.

In Elision werden die Lebensdauern mehrerer Objekte zu einem Objekt zusammengeführt.

Die Namen NRVO und RVO sind Namen für die Ausführung des Compilers, wenn der Standard dies zulässt.

Elision ist in Ihrem Beispiel zwischen der temporär erstellten Zeile return, dem Rückgabewert der Funktion und der benannten Variablen zulässig, in der Sie den Rückgabewert speichern. Jeder seriöse Compiler kann und wird diese Werte gemeinsam ausgeben, außer Sie Erklären Sie es ausdrücklich nicht über Compiler-Flags. Und in C++ 17 werden diese Abstriche verpflichtend sein.

Verwandte Themen