2009-10-28 82 views
10

中擦除()後,迭代器的有效性在std :: set invalidate iterator中擦除調用嗎?正如我從最後一行5號以下完成的..? 如果是有什麼更好的方式來擦除集的所有元素在std :: set

class classA 
{ 
public: 
    classA(){}; 
    ~classA(){}; 
}; 
struct structB 
{ 
}; 

typedef std::set <classA*, structB> SETTYPE;   
typedef std::map <int, SETTYPE>MAPTYPE; 

int __cdecl wmain (int argc, wchar_t* pArgs[]) 
{ 
    MAPTYPE mapObj; 
    /* 
     ... 
     .. Some Operation Here 
     ... 
     */ 
    for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++) 
    {  
     SETTYPE li=(*itr1).second; 
     for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
     { 
      classA *lt=(classA*)(*itr2); 
      li.erase(itr2); 
      delete lt; // Does it invalidate Iterator ? 
     } 
    } 
} 
+2

typedef std :: set SETTYPE; 我不知道你爲什麼要給StructB作爲std :: set的第二個模板參數。 std :: set只保存一個值(沒有與map一起使用的鍵),第二個模板參數用於爲集合提供比較函數(默認爲std :: less) – 2009-10-28 11:12:43

回答

2

既然你是剛剛顯然刪除集的每一個元素,你可以只是做:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
    { 
      classA *lt=(classA*)(*itr2); 
      delete lt; 
    } 
    li.clear(); // clear the elements 
+0

thx reko_t,這解決了我的問題問題 – Satbir 2009-10-28 11:32:37

41

從標準23.1.2

插入成員不應影響迭代器和對容器的引用的有效性,並且擦除成員應僅使迭代器和對擦除元素的引用無效。

編輯

在你的情況itr2被擦除,從而增加它會導致不確定的行爲無效。在這種情況下,你可以按照reko_t建議,在一般情況下,你可以試試這個:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{ 
    classA *lt=(classA*)(*itr2); 
    li.erase(itr2++); 
    delete lt; 
} 

這將增加迭代之前刪除它從組先前值。
順便說一句。 itr2沒有被delete lt;失效,但是被li.erase(itr2);

+3

由於這回答我的谷歌的「設置清除無效迭代器」,這也是我最喜歡的回答 – Chance 2012-04-23 17:02:08

+0

我最喜歡的答案! – Micka 2014-06-30 08:09:27

7

刪除是可以的。

問題是,您擦除 - 因此無效 - itr2,但它用於循環迭代。

i.a.w.第一次擦除後,++itr2有未定義的結果。

我在這種情況下使用的模式是這樣的:

while(itr2 != end()) 
{ 
    iterator toDelete = itr2; 
    ++itr2; // increment before erasing! 
    container.erase(toDelete); 
} 

一些非標準的STL impls具有擦除返回下一個迭代器,所以你可以這樣做:

while(itr2 != end()) 
    itr2 = container.erase(); 

這不便於攜帶,雖然。


set<A*,B>奇怪,雖然 - 在一個標準的IMPL,B是比較。