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?

questionAnswers(2)

yourAnswerToTheQuestion