假设我们有一个名为AAA
同时支持复制/移动的类:
class AAA
{
public:
AAA() = default;
~AAA() = default;
AAA(const AAA& rhs)
{
std::cout << "Copy constructor" << std::endl;
}
AAA(AAA&& rhs)
{
std::cout << "Move constructor" << std::endl;
}
};
在以下代码中,get_val
返回second
:
AAA get_val()
{
auto [ first, second ] = std::make_tuple(AAA{}, AAA{});
std::cout << "Returning - " << std::endl;
return second;
}
auto obj = get_val();
std::cout << "Returned - " << std::endl;
现在second
被复制,打印以下输出:
...
Returning -
Copy constructor
Returned -
这是不幸的,因为我对结果的期望是没有调用复制构造函数,或者至少它被隐式移动了。
为了避免复制,我必须明确地应用std::move
它。
return std::move(second);
然后我会收到以下结果:
...
Returning -
Move constructor
Returned -
我假设未执行RVO的原因是编译器可能会将second
其视为参考,而get_val
返回纯右值。
但是,为什么也不能期望隐式移动呢?在这种特殊情况下,在 return 语句上使用显式std::move
看起来并不直观,因为您通常不希望 RVO(在大多数情况下是比 move 更好的优化)意外消失。
由编译器 gcc 和 clang 测试-O3
。