2011-07-30 20 views
7

¿Es posible eliminar un elemento de un std::list si solo tiene el iterador que apunta al elemento que desea eliminar? Tengo una gran cantidad de funciones que toman iteradores para enumerar elementos, y sería un gran inconveniente tener que pasar el list propio a cada uno de ellos.Eliminar un elemento de una lista con solo su iterador

+1

Tenga en cuenta que usar un iterador de esta manera va en contra de su uso como patrón de diseño, pero eso no quiere decir que no sea lo correcto en muchas situaciones (por ejemplo, mirar los elementos de un conjunto) – Jeremy

+0

http: // stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while-iterating-through-it – nielsj

+0

@Jeremy: en realidad, no es el uso del iterador como un patrón de diseño. Sin embargo, tiene una semántica pobre con respecto a la invalidación del iterador. En muchos contenedores, la eliminación de un elemento invalida todos los iteradores, incluido el que está utilizando actualmente para iterar sobre los elementos. –

Respuesta

3

Editar:

Usted no puede con un único repetidor.

Si tiene los iteradores de inicio/final, puede usar el algoritmo std::remove para mover todos los elementos que desea borrar hasta el final y eliminarlos en un momento posterior.

Si no lo hace, o lo anterior no es factible con su diseño actual, le recomiendo que modifique sus funciones para tomar un std::pair<std::list<T>, std::list<T>::iterator> o algo así.

+2

Pero también requiere la lista. – Dani

+1

La función 'std :: remove()' no * elimina elementos del contenedor *, porque simplemente no puede. Echa un vistazo a [borrar idioma] (http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove). –

+0

@ André - Eso es lo que dije.Úselo para moverlos hasta el final _y elimínelos en un momento posterior_ – Node

0

No, esto no es posible. Como su nombre lo sugiere, el trabajo de un iterador es iterar sobre los elementos de una secuencia. Consulte SGI page on iterators para obtener un resumen del diseño de iteradores en la biblioteca estándar de C++.

+0

Como 'list' es una lista doblemente enlazada, ¿no podría escribir una función para manipular los punteros' next' y 'previous' para que elimine el elemento? ¿O eso sería realmente malo? ¿O es solo que los miembros son privados? –

+0

@Seth: sí, esto es técnicamente posible. Por ejemplo, en Java, los iteradores tienen un [método eliminar] (http://download.oracle.com/javase/1.4.2/docs/api/java/util/Iterator.html#remove()). Sin embargo, esto no es parte del diseño del iterador de C++. Supongo que el comité estándar prefirió la uniformidad con otros contenedores. –

+0

@Seth: esto podría hacerse para una versión específica de la biblioteca de un proveedor específico. Sin embargo, significa un montón de código no estándar (y definitivamente no portátil). Además, los miembros son probablemente privados. –

3

No, no puedes. Los iteradores son objetos livianos modelados después de punteros y no llevan una referencia al contenedor al que se refieren. (Aunque algunas implementaciones lo hacen internamente en modo Depuración.)

Del mismo modo que no puede "eliminar" un objeto de una matriz cuando todo lo que tiene es un puntero en la matriz, no puede quitar un objeto de un contenedor sin tener también acceso al contenedor.

-1

Puede hacerlo manualmente. iterador expone _M_node como el nodo actual. usted puede hacer algo como:

itr._M_node->_M_prev->_M_next = itr._M_node._M_next; 
+2

Este es solo el caso de un iterador específico en un contenedor específico en versiones específicas de una implementación específica, es un detalle de implementación e incluso se puede desactivar utilizando el token de preprocesador correcto. Además, podría estropear las partes internas del contenedor, lo que necesitaría saber para poder hacerlo. – sbi

+0

No dije que estaba limpio. tu advertencia es correcta aunque – Dani

+1

Sin mencionar que no actualizaste el puntero '_M_prev' de' _M_next' (porque es una lista dlinked). Eso es algo en lo que estaba pensando, pero este código también debe funcionar con diferentes versiones/compiladores. –

1

Mientras que otros han mencionado que no puede hacerlo, creo que puedo ofrecerle por qué.

Creo que el motivo técnico específico (más que el motivo del diseño) es que las listas realizan algunas tareas de mantenimiento, como el seguimiento del tamaño, por ejemplo, que requieren que se pasen ciertas acciones para permitir el mantenimiento.

Es por esta razón que cualquier ataque que pueda ofrecerse probablemente fallará.

+0

Eso es una buena idea, aunque parece que podría hacer que los iteradores le digan a su lista de padres que se están eliminando o algo así. –

Cuestiones relacionadas