6

Sagen wir, ich habe eine Funktion:Werden Rückgabewerte von Rvalue-Referenz in C++ 0x übergeben?

typedef std::vector<int> VecType; 
VecType randomVector(); 

int processing() 
{ 
    VecType v = randomVector(); 
    return std::accumulate(v.begin(), v.end(), 0); 
} 

Does C++ 0x sagen speziell die falsche Kopie wird von der Rückgabewert von randomVector abgewendet werden? Oder müsste ein Compiler das RVO implementieren? Es scheint mir, als ob der Wert randomVector() als ein rvalue behandelt werden sollte, und daher sollte der move-Konstruktor von v aufgerufen werden, aber ich bin mir nicht ganz sicher, ob das wahr ist.

+0

Keine gute Frage, IMHO. Der Standard kann nicht sinnvoll angeben, was eine Implementierung tun darf, nur was sie tun muss. –

+0

Eigentlich in dem Beispiel, das Sie angegeben haben, wird die Rückgabewertoptimierung von den meisten Compilern durchgeführt ... Es ist also effektiv ohne rvalue. Auch rvalue ist wichtiger für die Übergabe von Argumenten an Funktionen. – Artyom

+0

Der Titel der Frage ist ein bisschen irreführend. Ihre Funktion gibt einen R-Wert und keine Referenz zurück. Aber eine Rvalue-Referenz kann an sie binden, was passiert, wenn die Kopier-Elision aus irgendeinem Grund nicht ausgeführt werden kann und der Typ einen Move-Konstruktor hat (Der Move-Konstruktor-Parameter ist eine Rvalue-Referenz) – sellibitze

Antwort

7

Die Regel ist die folgende

  • Wenn der Compiler RVO tun kann, dann ist es erlaubt, es zu tun, und keine Kopie und keine Bewegung gemacht wird.
  • Andernfalls wird der entsprechende Konstruktor verwendet.

Wie Sie sagen, die nur vorübergehend ist ein R-Wert, und somit wird der Umzug Konstruktor ausgewählt, weil in der Regel in 13.3.3.2/3, das besagt, dass ein R-Wert Bezug besser als eine L-Wert-Referenz auf einen R-Wert bindet. Bei der Entscheidung, ob der Move oder der Kopierkonstruktor verwendet werden soll, wird die Überladungsauflösung daher den Move-Konstruktor bevorzugen. Die Regel, dass der Compiler RVO ausführen darf, wird unter 12.8/15 geschrieben.

2

Alle Rückgabewerte werden als rvalues betrachtet. Wenn der Compiler in diesem Fall kein RVO implementiert, muss er den Verschiebungskonstruktor anstelle des Kopierkonstruktors verwenden.

+1

Ich weiß nicht wie das "muss den Zug benutzen" interpretieren. AFAIU, nahm einen Compiler mit U/NRVO-Unterstützung, der Entscheidungsfluss ist wie folgt: 1) wenn RVO-freundlich, optimieren Sie alle verschieben/kopieren Operation, 2) sonst, wenn move construtor verfügbar ist, verwenden Sie 3) sonst, wenn kopieren Konstruktor verfügbar, benutze es 4) else ill-formed Programm – mloskot

+0

@mloskot Ich meine, der Move-Konstruktor ist ausgewählt, da er besser zum Überladen geeignet ist als der Copy-Konstruktor. – Motti

+2

Verstanden. Die implizite Annahme, dass move ctor existiert, war mir unklar. Als Bewegung wird ctor ausgewählt, aber nur wenn es existiert. – mloskot