¿Por qué std :: move previene RVO?

En muchos casos, cuando se devuelve un local desde una función, RVO se activa. Sin embargo, pensé que usar explícitamentestd::move al menos impondría el movimiento cuando RVO no ocurre, pero ese RVO todavía se aplica cuando es posible. Sin embargo, parece que este no es el caso.

#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;
}

Probé este código con VC ++ 11 y GCC 4.71, depuración y lanzamiento (-O2) config. La copia ctor nunca se llama. El movimiento ctor solo es llamado por VC ++ 11 en la configuración de depuración. En realidad, todo parece estar bien con estos compiladores en particular, pero que yo sepa, RVO es opcional.

Sin embargo, si uso explícitamentemove:

HeavyWeight MakeHeavy()
{
    HeavyWeight heavy;
    return std::move(heavy);
}

El movimiento ctor siempre se llama. Así que tratar de hacerlo "seguro" lo empeora.

Mis preguntas son:
- Por questd::move prevenir RVO?
- ¿Cuándo es mejor "esperar lo mejor" y confiar en RVO, y cuándo debo usar explícitamentestd::move? O, en otras palabras, ¿cómo puedo dejar que la optimización del compilador haga su trabajo y aún así hacer que se mueva si no se aplica RVO?

Respuestas a la pregunta(2)

Su respuesta a la pregunta