不。最佳做法是直接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