Betrachten Sie das folgende Beispiel:
#include <iostream>
struct foo {
foo(int) {}
foo(const foo&) { std::cout << "copy\n"; }
foo(foo&&) { std::cout << "move\n"; }
};
foo f() {
//return 42;
return { 42 };
}
int main() {
foo obj = f();
(void) obj;
}
Wenn mit gcc 4.8.1 mit -fno-elide-constructors
zusammengestellt RVO die Ausgabe zu verhindern, ist
move
Wenn in f
die return-Anweisung ohne geschweifte Klammern verwendet wird, dann , dann ist die Ausgabe
move
move
Wi th kein RVO, was passiert ist folgendes. f
muss ein temporäres Objekt vom Typ foo
, nennen wir es ret
, erstellt werden, um zurückgegeben werden.
Wenn return { 42 };
verwendet wird, dann ret
ist direkte aus dem Wert initialisiert 42
. Also wurde bisher kein Konstruktor für Kopieren/Verschieben aufgerufen.
Wenn return 42;
verwendet wird, dann vorübergehend eine andere, nennen wir es tmp
direkt von 42
initialisiert und tmp
bewegt wird ret
zu erstellen. Daher wurde bisher ein Move-Konstruktor aufgerufen. (Beachten Sie, dass tmp
ein R-Wert ist und foo
hat einen Umzug Konstruktor. Wenn es keine Bewegung Konstruktor war, dann würde die Kopie Konstruktor aufgerufen werden.)
Jetzt ret
ist ein R-Wert und verwendet wird obj
zu initialisieren. Daher wird der Bewegungsbaustein aufgerufen, um von ret
zu obj
zu wechseln. (Wiederum könnte unter gewissen Umständen der Kopierkonstruktor stattdessen aufgerufen werden.) Also entweder eine (für return { 42 };
) oder zwei (für return 42;
) Bewegungen passieren.
Wie ich in meinem Kommentar zu der Frage des OP sagte, ist dieser Beitrag sehr relevant: construction helper make_XYZ allowing RVO and type deduction even if XZY has noncopy constraint. Vor allem die hervorragende answer von R. Martinho Fernandes.
"Das ist vielleicht gut zu wissen" - außer dass Ihr Compiler ** tatsächlich RVO ausführt. –
@KonradRudolph Was, wenn aus irgendeinem Grund RVO in einem Beispiel nicht verwendet werden kann. Und selbst wenn - ich dachte, dass die C++ - Sprache RVO nicht garantiert. – Johannes
@KonradRudolph Sollte es Objekt nicht bewegen, anstatt RVO anzuwenden (oder möglicherweise zu überspringen)? –