¿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?