structures sirve que para examples data array c++ data-structures

examples - struct c++ para que sirve



Llamando a borrar con iterador vs const_iterator (5)

¿Por qué falla la llamada a la función miembro de erase de un contenedor con un const_iterator ?

Funciona con un iterator no const.


Con respecto a la constancia, puede pensar en un std::container<T>::const_iterator como una const T* .


Ese es el propósito del const_iterator. Los usas cuando los elementos a los que se accede a través de él no deben modificarse.


Esto no se compila porque container::iterator container::const_iterator y container::const_iterator son dos tipos distintos y la única versión (un argumento) de borrado es: iterator erase(iterator);

No aceptar un const_iterator puede verse como un defecto en el estándar de idioma: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2350.pdf

No hay ninguna razón particular para esta restricción. El iterador solo se usa para indicar una posición en el contenedor (modificable), y ni en el caso de insert o erase se modifica el "pointee" del iterador (en caso de erase , simplemente desaparece conceptualmente, lo que es una normalidad). Lo que hay que hacer para los objetos const).

El estándar actual indica una confusión entre "constancia de iterador y constancia de contenedor" (como lo hacen otras respuestas aquí), y parece que const_iterator podría ser aceptable para erase en C ++ 0x.

Como solución alternativa, puede obtener válidamente un iterator de un const_iterator porque el contenedor debe ser mutable en primer lugar.

La siguiente función solo es compilable para los iteradores de acceso aleatorio, ya que puede ser un poco demasiado lento para hacer esto con otros tipos de iteradores.

#include <vector> template <class Container> typename Container::iterator to_mutable_iterator(Container& c, typename Container::const_iterator it) { return c.begin() + (it - c.begin()); } int main() { int arr[] = {1, 5, 2, 5, 3, 4, 5, 1}; std::vector<int> vec(arr, arr + sizeof(arr) / sizeof(*arr)); for (std::vector<int>::const_iterator it = vec.begin(); it != vec.end(); ) { //if (*it = 5) { //const_iterator prevents this error if (*it == 5) { it = vec.erase(to_mutable_iterator(vec, it)); } else { ++it; } } }

Sin embargo, podría ser mejor reestructurar el código para que no necesite un const_iterator en primer lugar. En este caso, sería mejor usar el algoritmo std::remove . Si necesita realizar más trabajos de no mutación antes de borrar, puede extraerlo en un método separado, etc.


Solo quiero enfatizar en la corrección general de las respuestas / comentarios publicados por UncleBens, David Rodriguez e Ise Westeria.

Independientemente de los comportamientos de los compiladores actuales (o anteriores) anteriores a C ++ 11, la corrección constante de const_iterator (debería) se detiene inmediatamente en el sentido de que semánticamente es igual a const T * (o T * const); tenga en cuenta que T en sí puede ser un tipo de const de su propio! - por lo que efectivamente impide que el código modifique el objeto referenciado en el contenedor.

Sin embargo, como es perfectamente legal ''borrar'' un puntero de const en C ++ (¡pruébelo, funciona!), Debería ser (y el comportamiento ha sido corregido en C ++ 11) también legal para ''borrar'' una const iterador de un contenedor, siempre que el contenedor en sí no sea constante.

Parece que Visual Studio 2010 ya se está comportando correctamente al tener ''borrar'' aceptando const_iterator, lo que, por supuesto, me causó algunos dolores de cabeza para detectar algún otro error, lo que me llevó a esta publicación, que finalmente aclaró el comportamiento correcto de "borrar const_iterator" exactitud.


Un tipo const_iterator no se puede utilizar para modificar el valor de un elemento o el contenedor.