Почему std :: move предотвращает RVO?
Во многих случаях при возврате локального из функции, RVO вступает в силу. Однако я думал, что явно используяstd::move
по крайней мере, принудительное перемещение, когда RVO не происходит, но это RVO все еще применяется, когда это возможно. Однако, похоже, что это не так.
#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;
}
Я тестировал этот код с VC ++ 11 и GCC 4.71, отладка и выпуск (-O2
) конфиг. Копия ctor никогда не вызывается. Ctor перемещения вызывается только VC ++ 11 в конфигурации отладки. На самом деле, с этими компиляторами все в порядке, но, насколько мне известно, RVO не является обязательным.
Однако, если я явно используюmove
:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
ход ctor всегда вызывается. Поэтому попытка сделать его «безопасным» делает его еще хуже.
Мои вопросы:
- Почемуstd::move
предотвратить РВО?
- Когда лучше «надеяться на лучшее» и полагаться на RVO, и когда я должен явно использоватьstd::move
? Или, другими словами, как я могу позволить оптимизации компилятора выполнять свою работу и по-прежнему обеспечивать перемещение, если RVO не применяется?