2010-07-25 15 views
27

Digamos que tengo algún tipo de colección y obtuve un iterador para el comienzo. Ahora digamos que modifiqué la colección. ¿Puedo seguir utilizando el iterador de forma segura, independientemente del tipo de la colección o el iterador?¿Los iteradores de STL garantizan la validez después de que se cambió la colección?

Para evitar confusiones, aquí está el orden de las operaciones que hablo:

  1. Obtener un iterador de la colección.
  2. Modificar la colección (obviamente no es un elemento, sino la propia colección).
  3. Utilice el iterador obtenido en el paso 1. ¿Es aún válido de acuerdo con el estándar STL?
+0

Gracias a todos por las respuestas rápidas. – user88637

Respuesta

40

Depende del contenedor. p.ej. si es un vector, después de modificar el contenedor, todos los iteradores pueden ser invalidados. Sin embargo, si es un list, los iteradores irrelevantes para el lugar modificado seguirán siendo válidos.

  • iteradores de un vector se invalidan cuando se reasigna su memoria. Además, insertar o eliminar un elemento en el medio de un vector invalida todos los iteradores que apuntan a elementos que siguen al punto de inserción o eliminación. De esto se deduce que puede evitar que los iteradores de un vector se invaliden si usa reserve() para preasignar tanta memoria como el vector alguna vez usará, y si todas las inserciones y eliminaciones están al final del vector. [1]

  • La semántica de la invalidación del iterador para deque es la siguiente. Insert (incluidos push_front y push_back) invalida todos los iteradores que hacen referencia a deque. Erase en medio de deque invalida todos los iteradores que hacen referencia al deque. Erase al principio o al final de deque (incluidos pop_front y pop_back) invalida un iterador solo si apunta al elemento borrado. [2]

  • List s tienen la importante propiedad de que la inserción y empalme no invalidan los iteradores a la lista de elementos, y que incluso la eliminación invalida sólo los iteradores que apuntan a los elementos que se eliminan. [3]

  • Map tiene la importante propiedad de que la inserción de un nuevo elemento en una map no invalida iteradores que apuntan a los elementos existentes. Borrar un elemento de un mapa tampoco invalida ningún iterador, excepto, por supuesto, para los iteradores que realmente apuntan al elemento que se está borrando. [4] (lo mismo para set, multiset y multimap)

+1

Sin embargo, 'vector :: insert' (elemento individual) y' vector :: erase', devuelve un nuevo iterador válido. –

+1

Kenny: ¿Es verdad lo que dices según el estándar o verdadero porque así es como se suele implementar? ¿Puedes modificar tu respuesta para que también lo explique? Gracias. – user88637

+8

@ yossi1981: Esto está definido por el estándar. Las condiciones bajo las cuales los iteradores son invalidados se definen muy explícitamente en el estándar. –

4

No, los iteradores solo son buenos mientras que el contenedor iterado no se modifica. Si se modifica una colección, el iterador se debe obtener de nuevo.

+1

Estrictamente hablando eso no es cierto (la lista de ejemplos no sigue esas reglas). –

+1

La pregunta se hizo "independientemente del tipo de la colección (contenedor)". – m1tk4

+0

Independientemente de la pregunta, la declaración hecha en su respuesta es engañosa porque es cierta en algunos casos y falsa en (muchos) otros. – user487158

8

Eso depende de la colección en cuestión. Solo por ejemplo, modificar un std::vector (por ejemplo, agregar un elemento en alguna parte) puede invalidar todos los iteradores en ese vector.Por el contrario, con un std::list, los iteradores siguen siendo válidos cuando agrega otro elemento a la lista. En algunos casos, las reglas son aún más complejas (por ejemplo, si la memoria sirve, con un std::deque, agregar al comienzo o al final los iteradores existentes válidos, pero agregar cualquier otro lugar puede invalidarlos, pero mi memoria es lo suficientemente pobre como para verificar antes de depender de eso).

+2

¿Qué sucede si borras un elemento de la lista? ¿Qué pasa si se trata del elemento al que apunta el iterador? – m1tk4

+0

Al borrar el elemento al que hace referencia un iterador, se invalida ese iterador. Borrar cualquier otro elemento (s) no. –

+0

En otras palabras, si modifica la lista, hay circunstancias en las que invalidará el iterador (apuntando al elemento borrado), por lo que la validez del iterador no está garantizada, ¿correcto? – m1tk4

Cuestiones relacionadas