2013-03-21 24 views
1

我使用的地圖是這樣的:地圖裝滿垃圾紀錄

map<int,CUser*> m_mUsers; 

...

for (i = m_mUsers.begin(); i != m_mUsers.end(); i++) 
{ 
    if((*i).second->GetUserID() == pUser->GetUserID()) 
     (*i).second->OnDeviceLogout(pUser); 
} 

...

添加到地圖:

m_mUsers[ sd ] = pUser; 

刪除地圖:

i = m_mUsers.find(sd); 
m_mUsers.erase(i); 

當我運行這一點,主要是它的工作原理是我所期待。但很少,垃圾紀錄留在地圖上,所以當我嘗試通過什麼預期是一個空的地圖迭代,我碰上垃圾的記錄,並在I->二線> GetUserID崩潰()...什麼我做錯了嗎?

+0

如果什麼'i'是'end'?另外,一個問題可能被隱藏 - 這個「pUser」可能會損壞地圖中的元素,因爲它只是一個指針。 – 2013-03-21 11:34:40

+0

我有一個調試技巧給你。實現一個遍歷地圖並通過調用簡單的驗證函數來驗證每個節點的函數。當您從地圖中刪除節點時,將該節點標記爲無效,以便驗證功能投訴。然後在你的代碼周圍撒上驗證函數。通過這種方式,您可以儘早發現失效並更好地處理根本原因。 – 2013-03-21 11:39:30

回答

0

你不檢查i != m_mUsers.end()。這是不正確的,除非 它保證sd存在於你的情況。

i = m_mUsers.find(sd); 

//You should do the check before erasing 
if (i != m_mUsers.end()) { 
    m_mUsers.erase(i); 
} 

這應該正確地使代碼工作。順便說一句,我建議你使用 std::shared_ptrstd::unique_ptr的地圖mapped_type。 如果你沒有C++ 11可用,你可以嘗試technical reportboost libraries, 包括智能指針。 如果你只是想有一個參考,並不在乎在std::map管理CUser S, 你也可以做到這一點,這意味着你是不是CUser常務內存(在C++ 11只):

//No room for the question: Who is managing CUser memory in this map? 
std::map<int, std::reference_wrapper<CUser>> m_mUsers; 

如果你不修改的用戶,你可以連這個:

//Note I added const to CUser 
std::map<int, std::reference_wrapper<CUser const>> m_mUsers; 
+1

我acually我在Debian(GCC 4.4.5),它似乎太麻煩升級到4.7,所以我可能會用升壓去,容易修改我的代碼刪除原始指針的用法。謝謝大家對輸入! – 2013-03-28 21:44:01

+0

順便說一下,對於gcc 4.4.5,你可以在頭文件'tr1/utility'中使用'std :: tr1 :: reference_wrapper'。如果你要將代碼移植到不支持'std :: tr1'的編譯器中,那麼你可以堅持用'boost :: reference_wrapper'進行boost。這些都不需要C++ 11。如果你想要智能指針'tr1/memory'有'std :: tr1 :: shared_ptr',如果這是你需要的。沒有'unique_ptr',那個只是C++ 11。因此,根據您是否需要可移植性或依賴gcc,您可以選擇使用'boost'或'std :: tr1'。 – 2013-03-30 04:31:35