Dlaczego std :: move zapobiega RVO?
W wielu przypadkach po zwróceniu lokalnego z funkcji, RVO włącza się. Jednak myślałem, że to jest jawne użyciestd::move
wymuszałby przynajmniej poruszanie się, gdy RVO się nie dzieje, ale RVO jest nadal stosowane, gdy jest to możliwe. Wydaje się jednak, że tak nie jest.
#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;
}
Przetestowałem ten kod za pomocą VC ++ 11 i GCC 4.71, debugowania i wydania (-O2
) config. Kopiowanie nigdy nie jest wywoływane. Mechanizm przenoszenia jest wywoływany tylko przez VC ++ 11 w konfiguracji debugowania. Właściwie wszystko wydaje się być w porządku z tymi kompilatorami, ale według mojej wiedzy RVO jest opcjonalne.
Jeśli jednak użyję wyraźniemove
:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
ctor ruchu jest zawsze wywoływany. Tak więc uczynienie go „bezpiecznym” pogarsza sytuację.
Moje pytania to:
- Dlaczegostd::move
zapobiec RVO?
- Kiedy lepiej jest „mieć nadzieję na najlepsze” i polegać na RVO i kiedy powinienem to wyraźnie wykorzystaćstd::move
? Innymi słowy, w jaki sposób mogę pozwolić, aby kompilator optymalizował swoją pracę i nadal wymuszał ruch, jeśli RVO nie jest stosowane?