2008-12-09 45 views
2

我有一組對象,我遍歷,但是我可能會在迭代期間決定現在需要刪除一個(或多個)這些對象。原位刪除元素的最佳方式

我的代碼去如下:

if(! m_Container.empty()) 
    { 
     for( typedefedcontainer::iterator it = m_Container.begin(); 
       it != m_Container.end(); 
       ++it ) 
     { 
      if(! (SomeFunction((*it), "test", "TEST!", false)) ) 
      { 
      // If function returns false, delete object. 
       m_Container.erase(it); 
       AsyncResponseStore::iterator it = m_asyncResponses.begin(); 
      } 

     } 


    } 

但當然,當我刪除的對象,我得到一個錯誤:「地圖/套迭代器不遞增的。」有人可以提出一個更好的方法來做到這一點?

請參見: What happens if you call erase() on a map element while iterating from begin to end?

+0

爲什麼要測試容器的空白?如果爲空,for循環將永遠不會被輸入。 – 2008-12-09 16:56:43

回答

6

這取決於在容器上。列表容器支持枚舉過程中的刪除,方法是從表示列表中下一項的擦除方法中返回一個新的迭代器。地圖不支持這一點。

地圖的一個簡單方法是在單獨的列表中累積要擦除的項目,然後在完成地圖處理以擦除地圖中的項目時遍歷該列表。這假設您可以推遲刪除,直到迭代完成。如果沒有,那麼你別無選擇,只能重新啓動每次刪除的迭代。

0

修正由以下:

for( typedefedcontainer::iterator it = m_Container.begin(); 
     it != m_Container.end(); 
     ) 
{ 
    if(! (SomeFunction((*it), "test", "TEST!", false)) ) 
    { 
    // If function returns false, delete object. 
     m_Container.erase(it++); 
    } 
    else 
    { 
     ++i; 
    } 

} 

當一個元素被刪除,所有的指針到它變得無效。因此,通過使用++,我們可以避開它。感謝那些發佈建議的人。

+0

僅僅因爲你安全地前進到下一個迭代器,**並不意味着該迭代器是有效的。 onebyone有最好的解決方案。 – 2008-12-09 16:55:53

6

如果容器支持的話(我懷疑你的不對,但問題的標題是通用的,所以這可能是有用的人如果沒有你):

struct SomePredicate { 
    bool operator()(typedefedcontainer::value_type thing) { 
     return ! SomeFunction(thing, "test", "TEST", false); 
    } 
}; 

typedefedcontainer::iterator it; 
it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate()); 
m_Container.erase(it, m_Container.end()); 

m_Container必須具有擦除範圍的方法, ,其中包括任何序列或關聯容器。然而,它必須有一個可變的迭代器,而且我剛剛注意到我最初誤讀了錯誤信息:它說「map/set iterator not incrementable」。所以我猜你的容器是一張地圖或一套。

請注意,最後三個可能是一個真正了不起的單線,但這個邊距太窄,不能容納它。

此外,SomePredicate可能有一個構造函數的參數來存儲額外的參數給SomeFunction,因爲在現實生活中,我猜他們是非常量。

如果您使用boost:bind來構造仿函數,您實際上可以完全擺脫SomePredicate。那麼你的單線將會非常龐大​​。

[編輯:Rob Walker在他的回答中正確地指出了我在此做出的假設,並且問題沒有說明,也就是說,所有擦除都可以推遲到迭代 - 測試完成之後。如果SomeFunction通過隱藏路由(例如全局,或者因爲SomeFunction實際上是這個的成員函數)來訪問m_Container,並且它的結果取決於容器的內容,那麼我的代碼可能不等同於提問者的代碼。但我認爲我的代碼是「除非有一個不默認的原因」。)

相關問題