2010-01-27 9 views
5

Me preguntaba si algo como esto es seguro ...La eliminación de elementos durante la iteración a través de una lista - de seguridad

// Iterating through a <list> 
while (iter != seq.end()) { 
    if (test) { 
    iter = seq.erase(iter); 
    } else { 
    ++iter; 
} 

Sé que iteración a través de un vector de esta manera invalidaría el iterador, pero sería la Lo mismo ocurre en una lista? Supongo que no, ya que una lista es secuencial a través de punteros en lugar de estar "al lado" uno del otro en la memoria, pero cualquier tranquilidad sería útil.

+0

Nota: Eso también es válido con std :: vector, todos los iteradores existentes en el vector serán invalidados, pero el iterador devuelto por el método 'erase' es un iterador válido. –

+0

Correcto, pero seguro me refiero a que las operaciones continuas en el contenedor estarán bien ya que otros iteradores no se invalidarán (en este caso, además del que se borró). – Anonymous

+0

Si tiene * otros * iteradores, será mejor que se asegure de que no puedan estar apuntando al elemento que acaba de borrarse ... –

Respuesta

6

Esto está bien porque el método de borrado devuelve un nuevo iterador válido.

1

Sí, esta es la forma estándar de hacerlo. Ver STL efectivo, punto 9 (página 46).

0

Sí, esto es totalmente seguro. La función erase() devuelve un iterador al elemento que sigue al que se borró. Si no hubiera reasignado el resultado de erase() a iter, tendría problemas.

1

Sí - std::list::erase(): "Invalida solo los iteradores y las referencias a los elementos borrados".

Dicho esto, usted Probablemente no debería hacer esto en absoluto, parece que está tratando de imitar std::remove_if().

+2

Why not std :: list :: remove_if: http: //www.cppreference .com/wiki/stl/list/remove_if? – Ben

+0

@Ben: +1; buen punto. –

1

El estándar define el comportamiento erase para cada contenedor STL. Para std::list, solo se invalidan los iteradores de los elementos borrados. Sin embargo, el valor de retorno de erase no debe ser desreferenciable (podría ser list.end()).

Por lo tanto, para borrar todos los elementos en una lista que sigue es absolutamente válida:

.. it = l.begin(); 
while(it != l.end()) { 
    it = l.erase(it); 
} 

pero cuidado con algo como esto (escollo peligroso):

for (.. it = l.begin; it != l.end(); ++it) { 
     it = l.erase(it); 
    } 

Si es l.end(), se se incrementa dos veces (segunda vez por la cabeza del bucle). Baamm.

0

Como han explicado otros, su código no invalida el iterador utilizado en la función. Sin embargo, hace invalidar otros iteradores si la colección es un vector, pero no si la colección es una lista.

+0

Puede invalidar * otros * iteradores incluso si la colección es una lista, siempre que los * otros * iteradores apunten al elemento borrado. –

0

Como han mencionado otros, sí, funcionará. Pero recomendaría utilizar list::remove_if, ya que es más expresivo.

Cuestiones relacionadas