在運行時崩潰。將堆對象分配給std :: map
std::map<std::string, MyClass> myMap;
myValue = new MyClass();
myMap["myKey"] = *myValue;
我有2個要求:
- 即MyClass的實例被保持在堆(因此使用的新);
- 我可以通過關聯數組引用這些(因此使用std :: Map)。
爲什麼我不能在示例中成功使用解除引用運算符?我怎樣才能一次完成這兩項任務?
PS。我正在使用gcc。
在運行時崩潰。將堆對象分配給std :: map
std::map<std::string, MyClass> myMap;
myValue = new MyClass();
myMap["myKey"] = *myValue;
我有2個要求:
爲什麼我不能在示例中成功使用解除引用運算符?我怎樣才能一次完成這兩項任務?
PS。我正在使用gcc。
如果你失去了myValue
的範圍,那麼這是一個內存泄漏。因此,最好將MyClass*
存儲在您的地圖中。
std::map<std::string, MyClass*> myMap;
myValue = new MyClass();
myMap["myKey"] = myValue;
在給定的例子,也請務必delete
元素,同時刪除或從map<>
刪除。如果您不想擔心內存管理,可以使用智能指針(例如boost::shared_ptr
)。
另外,從你給出的例子我不知道爲什麼它應該崩潰,而提領*myClass
。你在複製構造函數MyClass::MyClass(const MyClass&)
中做了些奇怪的事情嗎?
我還沒有實現複製構造函數。我認爲這是問題,因爲std容器需要拷貝。這回答了我的「爲什麼」的問題,所以我接受了你的答案,因爲它涵蓋了所有的基礎。 –
您的最後一行在地圖中創建MyClass
的新實例,並在其上調用賦值運算符。我假設你的對象在它們中有一些指針,當你試圖釋放一些內存兩次時,你會得到一個錯誤。
與Java不同,C++中沒有隱式引用語義;如果要存儲指針,則需要使用std::map<std::string, MyClass*>
並相應地處理內存管理,或者如上所述,爲此使用某種形式的shared_prt
。
「相應地處理內存管理」,這是否意味着根據每個元素調用delete?所以在std容器中使用指針是安全的呢? –
這意味着容器中有指針的對象需要單獨進行生命週期管理,是的。除此之外,我沒有看到標準容器中有指針的問題。儘管如此,使用智能指針(而不是'std :: auto_ptr')的代碼或者提升容器將會爲你刪除對象更容易閱讀(和寫入,但你會更多地閱讀代碼的方式,而不是寫它......)和得到正確的。 –
您正在第2行創建一個新對象,並將其複製到地圖中。你可能正在尋找一個boost :: ptr_map。
爲什麼不'std :: map'? –
Flexo
如何定義'myValue'? MyClass是否有合適的拷貝構造函數和賦值操作符(如果需要,可以執行深層拷貝)? –
地圖應該保存指向MyClass的指針。 您的代碼會創建一個新實例,然後將副本插入到地圖中。 地圖中的副本實際上位於堆上,但由於地圖處理內存,因此刪除地圖中的實例並不安全。 如果您正在管理刪除其他地方的項目,那麼只需讓地圖上面提到一個指針即可。 – Pete