[英]C++11: Do move semantics get involved for pass by value?
我有一個看起來像這樣的API:
void WriteDefaultFileOutput(std::wostream &str, std::wstring target)
{
//Some code that modifies target before printing it and such...
}
我想知道通過這樣做啟用移動語義是否合理:
void WriteDefaultFileOutput(std::wostream &str, std::wstring&& target)
{
//As above
}
void WriteDefaultFileOutput(std::wostream &str, std::wstring const& target)
{
std::wstring tmp(target);
WriteDefaultFileOutput(str, std::move(tmp));
}
或者這只是編譯器應該能夠弄清楚的樣板?
如果您要使用不可移動的值制作副本,則應該更喜歡按值傳遞。 例如,您的const&
版本的WriteDefaultFileOutput
顯式復制參數,然后使用移動版本移動副本。 這意味着如果使用可移動值(xvalue或prvalue)調用WriteDefaultFileOutput
,那么它將被移動,如果使用左值調用它,它將被復制。
這意味着此功能的兩種形式之間沒有區別。 考慮一下:
WriteDefaultFileOutput(L"SomeString");
在第一種情況下,它將創建一個臨時的wstring
。 臨時值是prvalues,因此它將被“移動”到參數中(因為wstring
有一個移動構造函數)。 當然,任何有價值的編譯器都會忽略移動並簡單地將臨時構造直接放入參數中。
在你的第二種情況下,或多或少會發生同樣的事情。 創建臨時wstring
。 臨時值是prvalues,因此它們可以綁定到&&
參數類型。 因此,它將使用對臨時值的r值引用來調用函數的第一個版本。 唯一可能的區別在於編譯器不會忽略此舉。 即使這樣,移動也不是那么昂貴(取決於你的basic_string
實現)。
現在考慮一下:
std::wstring myStr{L"SomeString"};
WriteDefaultFileOutput(myStr);
在第一種情況下,對WriteDefaultFileOutput
的調用將導致myStr
值的副本進入函數參數。
在第二種情況下, myStr
是一個左值。 它無法綁定到&&
參數。 因此,它可以調用的唯一版本是const&
版本。 該函數將手動構建副本,然后使用另一個副本移動副本。
效果相同。 您的第一個版本的代碼較少,因此顯而易見。
一般來說,我會說只有兩個理由將參數作為&&
:
在您希望移動的所有其他情況下,只需取一個值。 如果用戶想要復制,請讓他們復制。 我想如果你想明確禁止復制參數,你可以采取一個&&
。 但主要問題是清晰度。
如果您使用值參數,並且用戶提供了可移動值,則將始終移動用戶提供的值。 例如,您&&
版本WriteDefaultFileOutput
不必實際上從它的參數移動數據。 當然可以。 但它沒有必要。 如果它花了一個值,那么它就已經聲明了數據。
因此,如果函數采用值參數,並且您看到std::move
進入該值,那么您就知道被移動的對象現在是空的。 保證已被移走。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.