2009-10-28 8 views
10

¿Cómo borrar la llamada en std :: set invalidate iterator? Como he hecho debajo del 5to de la última línea ...? si es así lo que es mejor forma de borrar todos los elementos de conjuntovalidez del iterador, después de la llamada a erase() en 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; No estoy seguro de por qué le está dando StructB como segundo argumento de la plantilla para el estándar. std :: set solo tiene un valor (no hay claves con set como con el mapa), el segundo argumento de plantilla se usa para proporcionar el functor de comparación para el conjunto (std :: less por defecto) –

Respuesta

2

Dado que se acaba de parecer a eliminar todos los elementos del conjunto, sólo se podía hacer:

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, esto resuelve mi problema – Satbir

41

De norma 23.1.2

Los miembros de inserción no afectarán la validez de los iteradores y las referencias al contenedor, y los miembros de borrado invalidarán únicamente los iteradores y las referencias a los elementos borrados.

EDITAR

En su caso itr2 se invalida después de borrar por lo incrementándolo provoca un comportamiento indefinido. En este caso, puede seguir los consejos reko_t, en general, puede intentar esto:

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

que incrementar iterador antes retirar su valor anterior del conjunto.
BTW. itr2 no es invalidado por delete lt;, pero por li.erase(itr2);

+3

Dado que esto responde a mi Google de "does set erase invalidate iterator", esta es mi respuesta favorita – Chance

+0

¡Mi respuesta favorita también! – Micka

7

La eliminación está bien.

El problema es que borra - y por lo tanto invalida - itr2, pero úselo para la iteración de bucle.

i.a.w. después del primer borrado, el ++itr2 tiene resultados indefinidos.

El patrón de uso en esta situación es la siguiente:

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

Algunos impls STL no estándar tienen borrar volver la próxima iterador, por lo que podría hacer:

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

que no es portátil, aunque.


la set<A*,B> es extraño, sin embargo - en un impl norma, B sería el comparador.

Cuestiones relacionadas