【发布时间】:2013-10-16 12:56:29
【问题描述】:
在许多情况下,当从函数返回局部变量时,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 永远不会被调用。 move ctor 仅在调试配置中由 VC++11 调用。实际上,特别是这些编译器似乎一切都很好,但据我所知,RVO 是可选的。
但是,如果我明确使用move:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
总是调用 move ctor。所以试图让它“安全”会让事情变得更糟。
我的问题是:
- 为什么
std::move会阻止 RVO? - 什么时候最好“抱最好的希望”并依赖 RVO,什么时候应该明确使用
std::move?或者,换句话说,如果不应用 RVO,我怎样才能让编译器优化完成它的工作并仍然强制移动?
【问题讨论】:
-
为什么现在人们还在谈论“希望最好”?他们使用什么样的编译器支持 C++11 但不能正确 RVO?
-
复制省略(RVO 背后的机制)仅在某些严格的条件下才被允许。写
std::move会阻止满足这些条件。 -
@KerrekSB 而 std::move 阻止的这些条件是......?
-
@Troy:你并不孤单。
-
@R.MartinhoFernandes:问题案例是允许行为更改的情况,即省略复制/移动构造函数调用。由于定义的测试用例必须包含副作用,因此您仅限于依赖复制省略和规则播放的优化。
标签: c++ c++11 move-semantics return-value-optimization