我知道用std::move
返回通常不是一个好主意,即
bigObject foo() { bigObject result; /*...*/ return std::move(result); }
而不是简单
bigObject foo() { bigObject result; /*...*/ return result; }
因为它妨碍了返回值优化。但是在具有多个不同回报的函数的情况下,尤其是类似
的函数class bar {
bigObject fixed_ret;
bool use_fixed_ret;
void prepare_object(bigObject&);
public:
bigObject foo() {
if(use_fixed_ret)
return fixed_ret;
else{
bigObject result;
prepare_object(result);
return result;
}
}
};
我认为在这样的功能中,正常的返回值优化是不可能的,所以放入
是个好主意 return std::move(result);
在这里,或者我应该去做(IMO丑陋,但这是有争议的)
bigObject foo() {
bigObject result;
if(use_fixed_ret)
result = fixed_ret;
else{
prepare_object(result);
}
return result;
}
答案 0 :(得分:33)
对于局部变量,大多数时候†在std::move
语句中不需要return
,因为语言实际上要求自动发生:
§12.8 [class.copy] p32
当满足或将满足复制操作的省略标准时,除了源对象是函数参数之外,并且要复制的对象由左值指定,重载决策要选择首先执行副本的构造函数,就像对象是由右值指定的一样。如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值。 [注意:无论是否发生复制省略,都必须执行此两阶段重载决策。如果未执行elision,它将确定要调用的构造函数,并且即使调用被省略,也必须可以访问所选的构造函数。 -end note ]
†复制省略在可以应用的地方受到限制(§12.8/31
)。一个这样的限制是源对象的类型必须与处理return语句时函数的cv-nonqualified返回类型相同。它也不适用于即将超出范围的局部变量的子对象。