schauen Sie bitte auf den folgenden Beispielcode:Warum wird der Kopierkonstruktor anstelle des Move-Konstruktors aufgerufen?
#include <iostream>
struct Foo {
Foo() { std::cout << "Default!\n"; }
Foo(const Foo& foo) { std::cout << "Copy!\n"; }
Foo(Foo&& foo) { std::cout << "Move!\n"; }
};
struct Bar {
Foo foo;
Bar() {}
Bar(Bar &that) : foo(that.foo) {}
Bar(Bar &&that) : foo(std::move(that.foo)) {}
};
Bar f() {
Bar bar;
return bar;
}
int main() {
Bar bar(f());
}
Ich bin davon aus, dass der Ausgang dieses Codes sein sollte:
Default!
Move!
aber was ich bekommen ist:
Default!
Copy!
Ich kann keinen Grund sehen, warum der Kopierkonstruktor anstelle des Move-Konstruktors aufgerufen wird. Wenn ich das Schlüsselwort const
vor Bar &that
in die Deklaration des Kopierkonstruktors von struct Bar
setze, habe ich das richtige Ergebnis. Ich weiß, dass es für viele Fälle besser ist, einen Konstantenreferenzwert zu verwenden, als nur einen L-Wert-Bezugswert für Kopierkonstruktoren, aber ich möchte nur den Grund wissen, warum dies passiert ist.
Warum wurde in diesem Beispiel Bar &
gegenüber Bar &&
bevorzugt, obwohl der Rückgabewert f()
als Prvalue betrachtet werden sollte? Warum löst das Schlüsselwort const
das Problem? Löst const
wirklich das Problem? Hat es etwas mit RVO (Return Value Optimization) zu tun? Oder ist das nur ein Compiler Bug?
Ich habe dieses Beispiel auf Visual C++ November 2012 CTP getestet.
Ich habe ein ähnliches Problem hier:
Copy constructor is being called instead of the move constructor
Aber ich kann immer noch nicht verstehen, warum.
Kann mir jemand helfen?
Kann nicht reproduziert werden. Mit GCC bekomme ich nur 'Default!' (Vernünftige NRVO bei der Arbeit), mit '-fno-elide-constructors' bekomme ich den erwarteten' Default! Bewegung! Bewege dich! '. Vielleicht ein Compiler b^Hshortcoming? –
ändere 'Bar (Bar & this)' in 'Bar (const Bar & that)'. –
@KerrekSB 1. Ich verstehe den Fall von NRVO. Aber warum zwei und nicht nur ein 'Move!' Erwartet wird, wenn der Kopierschutz ausgeschaltet ist? 2. Also sagst du, dass dies nur ein Fehler des Compilers ist, den ich benutzt habe? Danke trotzdem. –