una recorrer objetos lista iteradores guardar c++ list stl erase

c++ - recorrer - ¿El hecho de no borrar std:: list:: iterator invalida el iterador y destruye el objeto?



recorrer una lista c++ (5)

Como se trata de una lista vinculada, los elementos de la lista no tienen que estar "detrás" en la memoria. Si intentara lo mismo con un vector, probablemente (dado que el comportamiento no está definido) la experiencia

cout << *i

para ser impreso como 2.

Sin embargo, esta no es una forma muy segura de programación. Entonces, una vez que borre un iterador, asegúrese de no volver a usarlo, a menos que lo inicialice nuevamente con begin () o end (), etc.

¿Por qué lo siguiente imprime 2 ?

list<int> l; l.push_back( 1 ); l.push_back( 2 ); l.push_back( 3 ); list<int>::iterator i = l.begin(); i++; l.erase( i ); cout << *i;

Sé lo que erase , pero me pregunto por qué está bien. ¿O no está definido o depende del compilador?


Parece que el iterador aún apunta a esta memoria ...
Si escribes algo en este bloque,
quizás la próxima vez * arrojaría una falla de segmentación ...

lo siento por la especulación, aunque


Sí, es un comportamiento indefinido. Estás desreferenciando un tipo de puntero salvaje. No deberías usar el valor de i después de erase .

Y sí, erase destruye el objeto al que se apunta. Sin embargo, para los tipos de POD la destrucción no hace nada.

erase no asigna ningún valor "nulo" especial al iterador que se borra, el iterador ya no es válido.


Intenta compilar tu código con las opciones correctas, con un buen compilador y luego ejecutarlo. (Con VC ++, /D_DEBUG /EHs /MDd parece ser suficiente. Con g ++, -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC , al menos. Ambos compiladores necesitan incluso más opciones en general.) Debería bloquearse. (Lo hace cuando lo probé)


"destruir" un objeto significa que su memoria es recuperada y su contenido puede ser alterado (principalmente si el destructor escrito a mano lo hace, y posiblemente como resultado de almacenar cosas relacionadas con la memoria libre en su lugar). list :: erase le devuelve un nuevo iterador que debe usar en lugar del que se pasó como argumento (estaría tentado de hacer i = l.erase(i); un habbit).

De ninguna manera la destrucción implica que la memoria sea barrida, eliminada. La ubicación previamente válida sigue siendo válida en la mayoría de los casos desde el punto de vista de la CPU (es decir, puede recuperar valores), pero no se puede confiar porque otra operación puede reciclar esa ubicación para cualquier propósito en cualquier momento.

Es poco probable que veas *i lanzando una falla de segmentación, aunque eso podría suceder con tipos más complejos que usan punteros, pero es posible que veas que tiene valores nuevos.

Otras colecciones pueden tener un comportamiento más previsible que la lista. IIrc, un vector compactaría el área de almacenamiento, por lo que el valor anterior solo se vería desreferenciando i en casos excepcionales.