在很多情况下,当从函数中返回一个本地对象时,会触发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)配置下进行测试。拷贝构造函数从未被调用过。移动构造函数只被VC++11在调试模式下调用。实际上,对于这些编译器而言一切似乎都正常,但据我所知,返回值优化是可选的。
然而,如果我显式地使用move
:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
移动构造函数总是被调用。所以试图使其“安全”只会使情况变得更糟。
我的问题是:
- 为什么
std::move
会阻止RVO? - 何时最好“抱有最好的愿望”并依赖于RVO,何时应该显式使用
std::move
?换句话说,如何让编译器优化发挥作用并在不应用RVO时强制执行移动操作?