2009-10-28 7 views
10

Lösche Aufruf in Std :: Set Ungültig Iterator? Wie ich unten 5 von der letzten Zeile getan habe ..? ja wenn das, was besserer Weg ist es, alle Elemente von Satz zu löschenIterator-Gültigkeit, nach Erase() Aufruf in 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; Ich bin mir nicht sicher, warum Sie StructB als zweites Template-Argument für die std :: set geben. std :: set enthält nur einen Wert (es gibt keine Schlüssel mit set, wie es mit map), das zweite Template-Argument wird verwendet, um Vergleich functor für die Menge (std :: weniger standardmäßig) –

Antwort

2

Da Sie nur scheinbar jedes Element des Satzes zu löschen, könnten Sie einfach tun:

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, dies löst meine Problem – Satbir

41

Von Standard 23.1.2

Die Einfügeelemente dürfen die Gültigkeit von Iteratoren und Referenzen auf den Container nicht beeinträchtigen, und die Löschelemente sollen nur Iteratoren und Verweise auf die gelöschten Elemente ungültig machen.

EDIT

In Ihrem Fall ist ITR2 nach so Erhöhen Löschen für ungültig erklärt es nicht definiertes Verhalten verursacht. In diesem Fall Sie reko_t Rat folgen können, in der Regel können Sie dies versuchen:

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

der Iterator vor erhöht wird Entfernen aus Satz vorheriger Wert.
BTW. itr2 wird nicht durch delete lt; ungültig gemacht, aber durch li.erase(itr2);

+3

Da dies mein Google von beantwortet "löscht ungültig iterator löschen", das ist meine Lieblingsantwort – Chance

+0

meine Lieblingsantwort auch! – Micka

7

Das Löschen ist in Ordnung.

Das Problem ist, dass Sie löschen - und damit ungültig machen - itr2, aber verwenden Sie es für die Schleife Iteration.

i.a.w. Nach dem ersten Löschen hat der ++itr2 undefinierte Ergebnisse.

Das Muster, das ich in dieser Situation verwenden dies:

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

Einige Nicht-Standard-STL impls haben löschen Sie die nächste Iterator zurückgeben, so dass Sie tun können:

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

, die nicht tragbar ist, obwohl.


die set<A*,B>ist seltsam, wenn auch - in einem Standard-impl, B der Komparator sein würde.