2011-07-21 151 views
1

在運行時崩潰。將堆對象分配給std :: map

std::map<std::string, MyClass> myMap; 
myValue = new MyClass(); 
myMap["myKey"] = *myValue; 

我有2個要求:

  1. 即MyClass的實例被保持在堆(因此使用的新);
  2. 我可以通過關聯數組引用這些(因此使用std :: Map)。

爲什麼我不能在示例中成功使用解除引用運算符?我怎樣才能一次完成這兩項任務?

PS。我正在使用gcc。

+0

爲什麼不'std :: map '? – Flexo

+1

如何定義'myValue'? MyClass是否有合適的拷貝構造函數和賦值操作符(如果需要,可以執行深層拷貝)? –

+0

地圖應該保存指向MyClass的指針。 您的代碼會創建一個新實例,然後將副本插入到地圖中。 地圖中的副本實際上位於堆上,但由於地圖處理內存,因此刪除地圖中的實例並不安全。 如果您正在管理刪除其他地方的項目,那麼只需讓地圖上面提到一個指針即可。 – Pete

回答

4

如果你失去了myValue的範圍,那麼這是一個內存泄漏。因此,最好將MyClass*存儲在您的地圖中。

std::map<std::string, MyClass*> myMap; 
myValue = new MyClass(); 
myMap["myKey"] = myValue; 

在給定的例子,也請務必delete元素,同時刪除或從map<>刪除。如果您不想擔心內存管理,可以使用智能指針(例如boost::shared_ptr)。

另外,從你給出的例子我不知道爲什麼它應該崩潰,而提領*myClass。你在複製構造函數MyClass::MyClass(const MyClass&)中做了些奇怪的事情嗎?

+0

我還沒有實現複製構造函數。我認爲這是問題,因爲std容器需要拷貝。這回答了我的「爲什麼」的問題,所以我接受了你的答案,因爲它涵蓋了所有的基礎。 –

5

您可以使用此相反,使用升壓或TR1的shared_ptr:

std::map<std::string, shared_ptr<MyClass> > myMap; 
myValue = shared_ptr<MyClass>(new MyClass()); 
myMap["myKey"] = myValue; 

沒有所有權的問題,沒有內存泄漏。

+5

甚至boost :: ptr_map – Pete

+0

@Pete +1確實;我不確定OP是否可以使用boost,所以使用tr1更易於訪問 – stijn

1

您的最後一行在地圖中創建MyClass的新實例,並在其上調用賦值運算符。我假設你的對象在它們中有一些指針,當你試圖釋放一些內存兩次時,你會得到一個錯誤。

與Java不同,C++中沒有隱式引用語義;如果要存儲指針,則需要使用std::map<std::string, MyClass*>並相應地處理內存管理,或者如上所述,爲此使用某種形式的shared_prt

+0

「相應地處理內存管理」,這是否意味着根據每個元素調用delete?所以在std容器中使用指針是安全的呢? –

+1

這意味着容器中有指針的對象需要單獨進行生命週期管理,是的。除此之外,我沒有看到標準容器中有指針的問題。儘管如此,使用智能指針(而不是'std :: auto_ptr')的代碼或者提升容器將會爲你刪除對象更容易閱讀(和寫入,但你會更多地閱讀代碼的方式,而不是寫它......)和得到正確的。 –

0

您正在第2行創建一個新對象,並將其複製到地圖中。你可能正在尋找一個boost :: ptr_map。