2010-08-06 98 views
7
#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS 
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ 
    TypeName(const TypeName&);       \ 
    void operator=(const TypeName&) 

我是,從谷歌閱讀開源代碼。 爲什麼複製構造函數和賦值運算符是不允許的?爲什麼複製構造函數和賦值運算符是不允許的?

+1

它們被稱爲「複製構造函數」和「賦值運算符」。作爲賦值構造函數沒有這樣的事情。 – Sjoerd 2010-08-06 08:40:05

+2

我會稱它們爲「構造函數」和「賦值運算符」或「複製構造函數」和「複製賦值運算符」 – 2010-08-06 09:16:18

+2

我不會調用EVIL,這種顏色讓它們在惡劣的光線下着色。只需禁用它們就像boost:boost :: noncopyable – 2010-08-06 18:19:33

回答

12

防止正在複製或分配的類的實例。大多數類不應該允許複製。考慮一個例如BankAccount類 - 如果您正在爲銀行編寫軟件,如果您創建帳戶副本,然後將信用和借記應用於這些不同副本,他們就不會太高興。

+0

完美的例子。我多麼希望他們允許它:) !!!! – DumbCoder 2010-08-06 08:39:59

+0

+1 .... @DumbCoder如果你是該銀行軟件的編碼器,它將成爲可能! – KedarX 2010-08-06 10:30:58

+0

@Neil Butterworth:爲什麼不直接用單身呢? – MainID 2010-08-10 03:13:25

1

如果您的類型包含指針或引用成員,或者它沒有語義上的意義(例如它有一個必須在析構函數中釋放的資源句柄),那麼禁用複製構造函數和賦值運算符。在C++ 0x中(例如,在g ++ 4.4或更高版本中,在-std = C++ 0x模式下),您可以聲明它們已被刪除。在較早的編譯器中,您只需將它們聲明爲私有並且未實現。

7

複製構造函數和複製賦值操作符的問題是,如果編譯器沒有明確聲明,編譯器會自動生成實現。

這很容易導致意想不到的問題。如果一個類具有非平凡的析構函數,那麼它幾乎總是需要爲複製構造函數和複製賦值運算符提供它自己的實現(這是Law of the Big Three),因爲默認的編譯器生成的通常會做錯誤的事情。

違反三大法則往往會導致數據成員和內存損壞等錯誤。出現這種類型的錯誤並不罕見,因爲類的作者從來不會考慮複製行爲,而且消費者很容易無意中複製對象。除非類的作者已經真正考慮過如何正確地複製該類的實例(或者除非該類具有微不足道的析構函數),否則最好明確禁止複製以避免潛在的問題。實現可複製性可以推遲到實際需要時爲止。

+4

隨着即將推出的標準C++ 0x與移動構造器/作業的增加,這正成爲「五大法則」! – David 2010-08-06 13:16:44

+1

@David:移動構造函數/移動賦值運算符將被選入(如果忽略它們,編譯器將不會生成它們)。 – jamesdlin 2010-08-06 17:38:09

+0

你是對的,但如果你關心表現,你也會提供。 – David 2010-08-06 17:48:25