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