簡體   English   中英

C ++ 11:移動語義是否涉及傳遞值?

[英]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));
}

或者這只是編譯器應該能夠弄清楚的樣板?

“按值傳遞”可以表示復制或移動; 如果參數是左值,則調用復制構造函數。 如果參數是rvalue,則調用移動構造函數。 您不必執行任何涉及rvalue引用的特殊操作來獲取帶有pass by值的移動語義。

我在什么是移動語義中深入研究這個主題

如果您要使用不可移動的值制作副本,則應該更喜歡按值傳遞。 例如,您的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&版本。 該函數將手動構建副本,然后使用另一個副本移動副本。

效果相同。 您的第一個版本的代碼較少,因此顯而易見。

一般來說,我會說只有兩個理由將參數作為&&

  1. 您正在編寫移動構造函數。
  2. 您正在編寫轉發功能,需要使用完美轉發。

在您希望移動的所有其他情況下,只需取一個值。 如果用戶想要復制,請讓他們復制。 我想如果你想明確禁止復制參數,你可以采取一個&& 但主要問題是清晰度。

如果您使用值參數,並且用戶提供了可移動值,則將始終移動用戶提供的值。 例如,您&&版本WriteDefaultFileOutput 不必實際上從它的參數移動數據。 當然可以。 但它沒有必要。 如果它花了一個值,那么它就已經聲明了數據。

因此,如果函數采用值參數,並且您看到std::move進入該值,那么您就知道被移動的對象現在是空的。 保證已被移走。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM