2012-01-29 37 views
11

傳遞從我明白我能爲「禁用」的複製和定義私人拷貝構造函數和賦值操作符分配給我的對象:如果不允許轉讓和價值

class MyClass 
{ 
private: 
    MyClass(const MyClass& srcMyClass); 
    MyClass& operator=(const MyClass& srcMyClass); 
} 

但是,什麼是這種用法?
它被認爲是一種不好的做法?

我將不勝感激,如果你能描述的情況,其中我們有理由/爲「禁用」分配很有用,在這種方式拷貝構造函數。

+1

一個單就是一個例子。 – 2012-01-29 20:09:15

回答

11

當您的對象無法被複制時,它很有用。這絕對不是壞習慣。

舉例來說,如果你有一個代表網絡連接的一類,它是沒有意義的複製對象。如果你有一個班級代表多人遊戲中的一名玩家,那麼另一次你可能想要一個班級是不可複製的。這兩個類都代表在現實世界中無法複製的東西,或者複製(人,連接)無意義的東西。

另外,如果你想實現一個Singleton,它使物體不可複製的標準程序。

+0

謝謝,這很有道理。那麼賦值運算符呢? – LihO 2012-01-29 20:23:09

+3

@LihO一般來說,如果你禁用一個你禁用其他。如果你不禁用賦值操作符,你可以這樣做:'MyClass a,b; a = b;'如果你不禁用拷貝構造函數,你可以執行'MyClass b; MyClass a(b);'所以如果你不禁用它們,你可以避開另一個被禁用的。 – 2012-01-29 20:25:49

+0

是的,現在我明白了。 – LihO 2012-01-29 20:27:08

0

當你試圖實現一個Singleton模式是完全可以接受的使用私有的構造函數,因爲它的意思內本身和其他地方只實例化。 一旦被調用,構造函數就不能被撤銷。所以構造函數只有在檢查單例條件滿足後纔會被調用。

2

這是一個很常見的做法。有很多複製不合適的例子。

比方說,你的對象代表一個打開的服務器端套接字(即傳入網絡連接);製作該對象副本的語義是什麼?

5

一般來說,管理資源應該是沒有,可複製或有專門的拷貝語義的任何類。反過來也是如此:任何不可複製或需要特殊複製語義的類都是管理資源。在實踐中,C++語言中的「管理資源」意味着負責內存中的某些空間,或者連接到網絡或數據庫,或者文件句柄或撤銷事務等等。

資源管理捕獲了很多例子。這些職責是採取前綴操作,後綴操作以及可能的一些操作。例如,內存管理涉及獲取我們將要管理的內存地址的句柄,可能與該內存混亂,並最終釋放句柄(因爲如果你喜歡某事,就讓它免費)。

template<typename T> 
struct memory { 
    memory(T const& val = T()) : p(new T(val)) { } 
    ~memory() { delete p } 
    T& operator*() const { return *p; } 
private: 
    T* p; 
}; 

// ... 
{ 
    memory<int> m0; 
    *m0 = 3; 
    std::cout << *m0 << '\n'; 
} 

memory類幾乎是正確的:它會自動獲取底層的內存空間,並自動將其釋放,即使異常傳播一段時間後,它收購了其資源。但考慮這樣的場景:

{ 
    memory<double> m1(3.14); 
    memory<double> m2(m1); // m2.p == m1.p (do you hear the bomb ticking?) 
} 

因爲我們沒有爲memory提供專門的複製語義中,編譯器提供了它自己的拷貝構造函數和拷貝賦值。這些做錯誤事情:m2 = m1意味着m2.p = m1.p,使這兩個指針指向相同的地址。這是錯誤的,因爲當m2超出範圍時,它將其資源釋放爲一個好的責任對象,當m1超出範圍時,它也釋放其資源,同一資源m2已經釋放,完成雙重刪除 - 臭名昭着未定義的行爲場景。而且,在C++中,創建對象的副本是非常容易的,甚至不會注意到:函數根據值取其參數,按值返回它的參數,或者通過引用取其參數,然後調用另一個函數,該函數本身需要(或返回)參數值...更容易假設事情試圖得到複製。

這一切都是說,當一個班級的理由是管理資源時,你應該立即知道你需要處理複製。你應該決定

  • 你支持複製,而你決定的意思複製:資源的安全共享,進行底層資源的深層副本所以沒有共享任何或這兩種方法在copy-on-write合併或懶惰的副本。無論您選擇哪種路徑,您都需要提供專門的複製構造函數複製賦值運算符。
  • 或者您不支持任何形式的資源複製,在這種情況下您將禁用複製構造函數和複製賦值運算符。

我會走到目前爲止,並說資源管理是唯一的情況下,您禁用複製或提供專門的複製語義。這僅僅是The Rule of Three的另一個角度。

0

當你被允許創建對象的實例只有在像單身人士的情況下檢查你需要私有構造函數。當調用構造函數時,將調用對象實例,然後檢查是否還有其他實例沒有意義。所以我們所做的就是從main和inside中調用一個類的成員函數,該成員函數檢查另一個實例是否已經存在於內存中。如果不是構造函數被調用。別的中止。 檢查單體類或其他受保護的類,其中對象的數據必須保持安全,不應該被允許複製。

也檢查:Singleton Class in C++