不。最佳做法是直接return t;
。
如果类T
具有移动构造不会被删除,并通知t
是一个局部变量return t
可享有复制省略,其移动结构返回的对象,就像return std::move(t);
一样。但是return t;
仍然有资格复制/移动elision,因此可以省略构造,而return std::move(t)
总是使用移动构造函数构造返回值。
如果类T
中的移动构造函数被删除但复制构造函数可用,则return std::move(t);
将不会编译,而return t;
仍使用复制构造函数编译。与提到的@Kerrek不同,t
未绑定到右值引用。对于符合复制限制条件的返回值,有两阶段重载解决方案 - 尝试先移动然后复制,并且移动和复制都可能被取消。
class T
{
public:
T() = default;
T (T&& t) = delete;
T (const T& t) = default;
};
T foo()
{
T t;
return t; // OK: copied, possibly elided
return std::move(t); // error: move constructor deleted
return static_cast<T&>(t); // OK: copied, never elided
}
如果return
表达式是左值,并没有资格复制省略(最可能是你正在返回一个非本地变量或左值表达式),你还是想避免复制,std::move
将是有益的。但请记住,最好的做法是使复制elision可能发生。
class T
{
public:
T() = default;
T (T&& t) = default;
T (const T& t) = default;
};
T bar(bool k)
{
T a, b;
return k ? a : b; // lvalue expression, copied
return std::move(k ? a : b); // moved
if (k)
return a; // moved, and possibly elided
else
return b; // moved, and possibly elided
}
12.8(32)中的标准描述了该过程。
12.8 [class.copy]
32当的复制操作的省音的标准被满足或一个事实,即源对象是一个函数参数,并且是对象将被满足节省复制是由一个左值指定的,重载解析选择复制的构造函数首先执行,就好像该对象是由右值指定的一样。如果重载解析失败,或者如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是cv-qualified),则将该对象视为左值,重新执行重载解析。 [注意:无论是否发生复制删除,都必须执行这种两阶段重载解析。如果不执行elision,它将确定要调用的构造函数,即使该函数没有被使用,所选的构造函数也必须是可访问的。 - 注意]
[here](http://stackoverflow.com/questions/9827183/why-am-i-allowed-to-copy-unique-ptr)是一个类似的问题 – 2012-08-05 18:30:23
[相关FAQ] (http://stackoverflow.com/a/11540204/252000) – fredoverflow 2012-08-06 08:17:46