2009-10-05 73 views
1

我有以下幾點:有問題的std :: multimap中

enum Type 
{ One = 0, Two}; 

class MySubClass 
{ 
private: 
MySubClass(); // prohibited 
MySubClass(const MySubClass&); // prohibited 
MySubClass & operator (const MySubClass&); // prohibited 
public : 
MySubClass(int x); 
}; 

class MyClass 
{ 
MyClass(int x) : m_x(new SubClass(x)) 
{} 
~MyClass() 
{ delete m_x; } 
private : 
MySubClass * m_x; 
}; 

typedef multimap<Type, MyClass> my_multimap; 
typedef pair<Type, MyClass> my_pair; 

我試圖做到以下幾點:

my_multimap my_map; 
my_map.insert(my_pair(One, MyClass(5))); 

而且我得到一個未處理的異常結果,應用程序試圖讀取0xfeeefeee等

發生了什麼事?我怎樣才能解決這個問題? 請注意,這是我正在處理的簡化案例;

+1

您不必爲「禁止」默認的構造函數,因爲提供了一個手寫的構造有效地防止編譯器生成一個默認的。通過這樣做,您可以暴露自己實際上在沒有實現後面使用默認構造函數(來自您的班級或朋友)。 – 2009-10-05 12:16:56

回答

4

MyClass沒有定義拷貝構造函數。但是,std::pair需要使用MyClass的複製構造函數。據推測,它是使用MyClass的默認拷貝構造函數,這將給指針m_x的拷貝構造的對象副本。當它們被破壞時,你將面臨多次刪除。

1

你必須寫一個拷貝構造函數。

發生了什麼事情,MyClass被值 複製,指針在副本之間共享。 現在,當對象被銷燬的 指針被刪除multiplie倍。

像這樣:

class MyClass 
{ 
MyClass(int x) : m_x(new SubClass(x)) {} 
MyClass(const MyClass& myclass) : m_x(new SubClass(*myclass.m_x)) {} 
~MyClass() { delete m_x; } 
private : 
MySubClass * m_x; 
}; 

顯然子類需要一個拷貝構造函數了。

+0

儘管它可能不會用於顯示的代碼中,但仍會遺漏賦值運算符。此外,派生類不需要定義複製構造函數,編譯器生成的就沒問題。 – sbi 2015-07-02 11:25:10

5

有一個經驗法則,叫「規則三」:只要你有一張析構函數或賦值運算符或拷貝構造函數,它很可能你會需要他們三個。你的代碼也不是這個規則的例外。

想象一下如果你的類型的對象複製會發生什麼。這

MyClass obj1; 
MyClass obj2(obj1); 

代碼也會崩潰。

1

正如大家提到的,類需要一個工作拷貝構造函數才能存儲在任何標準容器中。但是,在這種情況下,MySubClass會禁用複製。這幾乎給你兩個選擇:

1)MyClass也應該是不可複製的,在這種情況下,你必須在multimap中存儲(智能)指針。

2)複製的MyClass實例應共享MySubClass實例。爲了實現這一點,最簡單的就是用boost::shared_ptr<MySubClass>std::tr1::shared_ptr<MySubClass>更換指針成員。這樣做可以使您免於執行析構函數,複製構造函數和賦值運算符。