Por que o std :: move impede o RVO?
Em muitos casos, ao retornar um local de uma função, o RVO entra em ação. No entanto, pensei que usar explicitamentestd::move
pelo menos reforçaria a movimentação quando a RVO não acontece, mas a RVO ainda é aplicada quando possível. No entanto, parece que este não é o 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;
}
Eu testei este código com VC ++ 11 e GCC 4.71, depurar e liberar (-O2
) config. O copiador nunca é chamado. O ctor de movimento é chamado apenas pelo VC ++ 11 em debug config. Na verdade, tudo parece estar bem com esses compiladores em particular, mas que eu saiba, o RVO é opcional.
No entanto, se eu usar explicitamentemove
:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
o diretor de movimento é sempre chamado. Então, tentar torná-lo "seguro" torna tudo pior.
Minhas perguntas são:
- Porquestd::move
prevenir RVO?
- Quando é melhor "esperar pelo melhor" e confiar no RVO, e quando devo usar explicitamentestd::move
? Ou, em outras palavras, como posso deixar a otimização do compilador funcionar e ainda impor a movimentação se a RVO não for aplicada?