print iterators for declarar advance c++ iterator

iterators - list iterator c++



Problema con std:: map:: iterator después de llamar a erase() (5)

"it" aún apunta a la misma ubicación, el borrado no actualiza el iterador por sí mismo, debe hacerlo reiniciando el iterador. En efecto, "it" apunta a la ubicación antigua que se ha borrado del vector pero aún contiene los datos antiguos.

// erasing from map #include <iostream> #include <map> using namespace std; int main () { map<char,int> mymap; map<char,int>::iterator it(mymap.begin()); // insert some values: mymap[''a'']=10; mymap[''b'']=20; mymap[''c'']=30; mymap[''d'']=40; mymap[''e'']=50; mymap[''f'']=60; it=mymap.find(''a''); mymap.erase (it); // erasing by iterator // show content: for (; it != mymap.end(); it++ ) cout << (*it).first << " => " << (*it).second << endl; return 0; }

¿Por qué esto da una salida como

a => 10 b => 20 c => 30 d => 40 e => 50 f => 60

No debería eliminarse "a => 10" todos modos, pero si lo declaro it = mymap.begin() en el bucle for, todo es perfecto. ¿por qué?

programa adaptado de: http://www.cplusplus.com/reference/stl/map/erase/


Borrar un elemento de un map invalida los iteradores que apuntan a ese elemento (después de que todo ese elemento haya sido eliminado). No debes reutilizar ese iterador.

Dado que C ++ 11 erase() devuelve un nuevo iterador que apunta al siguiente elemento, que se puede usar para continuar la iteración:

it = mymap.begin(); while (it != mymap.end()) { if (something) it = mymap.erase(it); else it++; }

Antes de C ++ 11, tendría que avanzar manualmente el iterador al siguiente elemento antes de que tenga lugar la eliminación, por ejemplo, como este:

mymap.erase(it++);

Esto funciona porque el efecto colateral posterior al incremento it++ ocurre antes de que erase() elimine el elemento. Como esto tal vez no sea inmediatamente obvio, se debería preferir la variante de C ++ 11 anterior.


Esto tiene que ver con cómo se implementa el map . Digamos que es un árbol de algún tipo, como:

class map_node { char key; int value; map_node* next; ... };

Cuando erase() el iterador, elimina el nodo del árbol y desasigna su espacio. Pero hasta que se sobrescriba la ubicación de la memoria, el contenido del nodo aún está en la memoria. Es por eso que puede obtener no solo el valor, sino también el siguiente elemento del árbol. Por lo tanto, su resultado es completamente esperado.


Llamar a erase() invalida el iterador. En este caso, lo que sucede es que el iterador apunta al valor residual que queda en la memoria (¡pero no confíe en este comportamiento indefinido!). Restablezca el iterador con it=mymap.begin() antes del bucle para obtener los resultados deseados.

http://codepad.org/zVFRtoV5

Esta respuesta muestra cómo borrar elementos mientras se itera sobre un std::map :

for(map<T, S*>::iterator it = T2pS.begin(); it != T2pS.end(); T2pS.erase(it++)) { // wilhelmtell in the comments is right: no need to check for NULL. // delete of a NULL pointer is a no-op. if(it->second != NULL) { delete it->second; it->second = NULL; } }


it no es válido después de mymap.erase(it) . Esto significa que puede hacer lo que quiera.