4 回答

TA貢獻1880條經驗 獲得超4個贊
我要說三法則成為三,四,五的規則:
每個類應明確定義以下一組特殊成員函數:
沒有
析構函數,復制構造函數,復制賦值運算符
此外,顯式定義析構函數的每個類可以顯式定義移動構造函數和/或移動賦值運算符。
通常,以下一組特殊成員函數是明智的:
無(對于許多隱式生成的特殊成員函數正確且快速的簡單類)
析構函數,復制構造函數,復制賦值運算符(在這種情況下,類不可移動)
析構函數,移動構造函數,移動賦值運算符(在這種情況下,該類將不可復制,對于底層資源不可復制的資源管理類很有用)
析構函數,復制構造函數,復制賦值運算符,移動構造函數(因為復制省略,如果復制賦值運算符按值獲取其參數,則沒有開銷)
析構函數,復制構造函數,復制賦值運算符,移動構造函數,移動賦值運算符
請注意,不會為顯式聲明任何其他特殊成員函數的類生成移動構造函數和移動賦值運算符,不會為顯式聲明移動構造函數或移動的類生成復制構造函數和復制賦值運算符賦值運算符,并且具有顯式聲明的析構函數和隱式定義的復制構造函數或隱式定義的復制賦值運算符的類被視為已棄用。特別是,以下完全有效的C ++ 03多態基類
class C {
virtual ~C() { } // allow subtype polymorphism
};
應改寫如下:
class C {
C(const C&) = default; // Copy constructor
C(C&&) = default; // Move constructor
C& operator=(const C&) = default; // Copy assignment operator
C& operator=(C&&) = default; // Move assignment operator
virtual ~C() { } // Destructor
};
有點煩人,但可能比替代(自動生成所有特殊成員函數)更好。
與三巨頭規則相反,未遵守規則可能會造成嚴重損害,未明確聲明移動構造函數和移動賦值運算符通常很好,但在效率方面通常不是最理想的。如上所述,只有在沒有顯式聲明的復制構造函數,復制賦值運算符或析構函數時,才會生成移動構造函數和移動賦值運算符。對于自動生成復制構造函數和復制賦值運算符,這與傳統的C ++ 03行為不對稱,但更安全。因此,定義移動構造函數和移動賦值運算符的可能性非常有用,并創建了新的可能性(純粹的可移動類),但遵循C ++ 03三巨頭規則的類仍然可以。
對于資源管理類,如果無法復制基礎資源,則可以將復制構造函數和復制賦值運算符定義為已刪除(計為定義)。通常你仍然想要移動構造函數和移動賦值運算符。復制和移動賦值運算符通常使用swap,如在C ++ 03中實現。如果你有一個移動構造函數和移動賦值運算符,則特殊化std::swap將變得不重要,因為泛型std::swap使用移動構造函數并移動賦值運算符(如果可用),并且應該足夠快。
不用于資源管理的類(即,沒有非空的析構函數)或子類型多態(即,沒有虛擬析構函數)應該不聲明五個特殊成員函數; 它們都將自動生成并且行為正確且快速。

TA貢獻1834條經驗 獲得超8個贊
是的,我認為為這些類提供移動構造函數會很好,但請記?。?/p>
這只是一種優化。
僅實現一個或兩個復制構造函數,賦值運算符或析構函數可能會導致錯誤,而沒有移動構造函數可能會降低性能。
無需修改即可始終應用移動構造函數。
有些類總是分配它們的指針,因此這些類總是在析構函數中刪除它們的指針。在這些情況下,您需要添加額外的檢查,以確定其指針是已分配還是已被移走(現在為空)。
- 4 回答
- 0 關注
- 644 瀏覽
添加回答
舉報