Warum verhindert std :: move RVO?
In vielen Fällen, wenn ein Local von einer Funktion zurückgegeben wird, greift RVO ein. Ich dachte jedoch, dass dies explizit verwendet wirdstd::move
würde zumindest das Verschieben erzwingen, wenn RVO nicht stattfindet, aber dieses RVO wird weiterhin angewendet, wenn dies möglich ist. Dies scheint jedoch nicht der Fall zu sein.
#include "iostream"
class HeavyWeight
{
public:
HeavyWeight()
{
std::cout << "ctor" << std::endl;
}
HeavyWeight(const HeavyWeight& other)
{
std::cout << "copy" << std::endl;
}
HeavyWeight(HeavyWeight&& other)
{
std::cout << "move" << std::endl;
}
};
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return heavy;
}
int main()
{
auto heavy = MakeHeavy();
return 0;
}
Ich habe diesen Code mit VC ++ 11 und GCC 4.71 getestet, debuggen und freigeben (-O2
) config. Der Kopierer wird nie aufgerufen. Der move ctor wird nur von VC ++ 11 in der Debug-Konfiguration aufgerufen. Eigentlich scheint bei diesen Compilern alles in Ordnung zu sein, aber meines Wissens ist RVO optional.
Allerdings wenn ich das explizit benutzemove
:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
der move ctor wird immer aufgerufen. Der Versuch, es "sicher" zu machen, macht es noch schlimmer.
Meine Fragen sind:
- Warum tutstd::move
RVO verhindern?
- Wann ist es besser, "auf das Beste zu hoffen" und sich auf RVO zu verlassen, und wann sollte ich dies ausdrücklich anwenden?std::move
? Oder mit anderen Worten, wie kann ich die Compileroptimierung ihre Arbeit machen lassen und trotzdem verschieben, wenn RVO nicht angewendet wird?