簡體   English   中英

C ++ 11移動構造函數

[英]C++11 move constructor


考慮以下類,實現移動構造函數的正確方法是什么:

class C {
public:
    C();
    C(C&& c);
private:
    std::string string;
}

當然,其想法是避免復制string或將其重新分配兩次。
讓我們假設基本示例只是為了清楚起見,我確實需要一個move構造函數。


我試過了:

C::C(C&& c) {
    //move ctor
    string = std::move(c.string);
}

C::C(C&& c) : string(std::move(c.string)) {
    //move ctor
}

兩者都可以在gcc 4.8上正常編譯,並且可以正常運行。 看來選項A是正確的行為, string被復制而不是與選項B一起移動。
這是move構造函數的正確實現嗎?

由於std::string本身具有move-ctor,因此C隱式定義的move-ctor將負責適當的move操作。 您可能無法自己定義。 但是,如果您有任何其他數據成員,尤其是:

12.8復制和移動類對象

12隱式聲明的copy / move構造函數是其類的內聯公共成員。 如果X具有以下功能,則默認將類X的復制/移動構造函數定義為已刪除(8.4.3):

—具有非平凡的對應構造函數且X是類聯合類的變體成員,

—無法復制/移動的類類型M(或其數組)的非靜態數據成員,因為應用於M的相應構造函數的重載分辨率(13.3)導致歧義或函數從該類中刪除或不可訪問默認的構造函數,或者

—無法復制/移動的直接或虛擬基類B,因為將重載解析(13.3)應用於B的相應構造函數,會導致歧義或從默認構造函數中刪除或無法訪問的函數,或者

—對於move構造函數,是非靜態數據成員或直接或虛擬基類,其類型沒有move構造函數且不可復制。

13如果類X的復制/移動構造函數既不是用戶提供的也不是用戶刪除的,並且

—類X沒有虛擬函數(10.3)和虛擬基類(10.1),函數(10.3)和虛擬基類(10.1),以及

—選擇復制/移動每個直接基類子對象的構造函數很簡單,並且

—對於類類型(或其數組)的X的每個非靜態數據成員,選擇用來復制/移動該成員的構造函數都是微不足道的; 否則,復制/移動構造函數是不平凡的。

您可能想實現自己的move-ctor。

如果您需要move-ctor,請使用初始化列表語法。 總是! 否則,您可能會為每個對象的默認構造最終在初始化列表中未提及(這是僅對具有非默認ctor的成員對象強制執行的操作)。

您的兩個變體都會移動字符串。 第二個變體應該是首選,因為它不會默認構造一個空字符串,只是隨后移動分配它。

檢查您的測試用例,然后檢查編譯器的bugzilla列表。 如果要確保兩種情況都移動,則需要跟蹤對string::operator=(string&&) (第一種情況) string::string(string&&) (第二種情況)的調用。

兩個構造函數都應該工作。 因此,兩者都是正確的move構造函數。 第二個可能會更有效,因為第一個默認構造string只是為了分配給它,而第二個默認只是移動構造它,因此應該更有效。 如果第二個效率較低,我會懷疑是編譯器錯誤(請記住,當前編譯器對C ++ 11的支持仍不完整)或測試方法有缺陷(您將如何精確地測試復制與移動,並且確定移動構造函數是否正確)兩種情況下都不會調用賦值操作嗎?)。

當然,只要有可能,您只要讓編譯器通過C(C&&) = default;生成您的構造函數即可C(C&&) = default;

此處無需實現move構造函數,因為您不必手動管理內存。 僅當在類中手動使用動態數組時,移動構造函數才有用。

您仍然可以顯式地讓編譯器創建默認的move構造函數,即使您不要求它也應該已經完成​​:

C(C&& c) = default;

暫無
暫無

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

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