4 回答

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

TA貢獻(xiàn)1858條經(jīng)驗 獲得超8個贊
我無法相信沒有人與此有關(guān)。
基本上,文章認(rèn)為“零法則”。我引用整篇文章是不合適的,但我認(rèn)為這是重點(diǎn):
具有自定義析構(gòu)函數(shù),復(fù)制/移動構(gòu)造函數(shù)或復(fù)制/移動賦值運(yùn)算符的類應(yīng)專門處理所有權(quán)。其他類不應(yīng)該有自定義析構(gòu)函數(shù),復(fù)制/移動構(gòu)造函數(shù)或復(fù)制/移動賦值運(yùn)算符。
這一點(diǎn)是恕我直言的重要:
常見的“包中所有”類包含在標(biāo)準(zhǔn)庫中:
std::unique_ptr
和std::shared_ptr
。通過使用自定義刪除對象,兩者都具有足夠的靈活性來管理幾乎任何類型的資源。

TA貢獻(xiàn)1877條經(jīng)驗 獲得超6個贊
我不這么認(rèn)為,三個規(guī)則是一個經(jīng)驗法則,規(guī)定實現(xiàn)以下一個但不是全部的類可能是錯誤的。
復(fù)制構(gòu)造函數(shù)
分配操作員
析構(gòu)函數(shù)
但是,省略移動構(gòu)造函數(shù)或移動賦值運(yùn)算符并不意味著錯誤。它可能是錯過了優(yōu)化的機(jī)會(在大多數(shù)情況下),或者移動語義與此類無關(guān),但這不是錯誤。
盡管在相關(guān)時定義移動構(gòu)造函數(shù)可能是最佳實踐,但這不是強(qiáng)制性的。在許多情況下,移動構(gòu)造函數(shù)與類(例如std::complex
)無關(guān),并且在C ++ 03中行為正確的所有類將繼續(xù)在C ++ 0x中正常運(yùn)行,即使它們沒有定義移動構(gòu)造函數(shù)。

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