2013-09-22 46 views
2

在SO中讀取答案,他通過了vectormove。我認爲正確的方法是通過簡單而不使用move傳遞可移動的對象

class B 
{ 
    std::vector<T> data; 

public: 
    B(std::vector<T> p) : data(std::move(p)) {} 
           ^^^^^^^^^^^^ 
            ? 
}; 

第二種方式是:

class B 
{ 
    std::vector<T> data; 

public: 
    B(std::vector<T> p) : data(p) {} 
}; 

哪一個是正確的?

+4

第二個讓兩個副本 – billz

+0

如果你需要複製語義,使用拷貝語義。如果您需要移動語義,請使用移動語義。沒有更正確的解決方案。 – IInspectable

+2

你需要移動,因爲p是左值 – billz

回答

2

函數參數已經被值取得,所以已經創建了一個副本。本地對象p毫無疑問地是你自己和你的,所以你可以無條件地從它移動。

以價值爲參數的美妙之處在於它適用於左值和右值:對於左值,您可以製作一個真正的副本,因爲除此之外沒有別的辦法可以做,但對於右值,函數參數本身可以通過移動,所以有史以來只有一個昂貴的施工發生,而其他一切都被移動了。

2

當你從一個左值構造一個對象時,它將被複制。當你從非const右值構造一個對象時,它可以被移動(它是否被移動取決於具有移動構造器的類)。在你的構造函數中,p顯然是一個左值:它有一個名字。但是,它是一個局部變量,即將消失,即從中移出即爲保存:std::move(p)使對象看起來好像是一個右值:在此上下文中,該值是正確的路徑。

請注意,如果您返回對象,則建議會有所不同:在return語句中返回的本地值會自動從中移出。使用std::move()只會加強聲明,但也會阻止完全消除複製/移動的可能性。在您的構造函數中,複製/移動不能被刪除,因爲複製刪除僅對return語句中的臨時對象或本地對象起作用。

T f() { 
    T local; 
    return local; // good: elided, moved, or copied in this order of preference 
} 
T g() { 
    T local; 
    return std::move(local); // bad: can't be elided and will be moved or copied 
}