2010-09-23 9 views
19

Estoy tratando de eliminar el contenido del vector y me aparece un error - el iterador vectorial no se puede incrementar, ¿por qué?¿Por qué este iterador vectorial no es incrementable?

Esta es mi destructor:

City::~City() 
{ 
    vector <Base*>::iterator deleteIterator; 
    for (deleteIterator = m_basesVector.begin() ; deleteIterator != m_basesVector.end() ; deleteIterator++) 
     m_basesVector.erase(deleteIterator); 
} 

gracias.

+5

Suponiendo que 'm_basesVector' es un miembro de' City', no hay necesidad de borrar sus elementos; su destructor está a punto de hacer eso por ti. –

+3

Sabe que esto no eliminará los objetos a los que apuntan sus apuntadores. Tendría que llamar a 'eliminar deleteIterator;' para lograr eso (si eso es lo que quiere). Sin embargo, en ese caso, debería preferir 'boost :: ptr_vector'. –

+0

Ver [allí] (http://stackoverflow.com/questions/307082/). – Wok

Respuesta

41

erase invalida el iterador. No puedes usarlo más. Por suerte para usted, devuelve un iterador que puede utilizar:

vector <Base*>::iterator deleteIterator = m_basesVector.begin(); 
while (deleteIterator != m_basesVector.end()) { 
    deleteIterator = m_basesVector.erase(deleteIterator); 
} 

O:

m_basesVector.clear(); 

¿Es usted responsable de liberar la memoria que se refieren los punteros en el vector? Si esa es la razón por la cual estás iterando (y tu programa real tiene más código que no has mostrado, eso libera esos objetos en el ciclo), entonces ten en cuenta que borrar desde el comienzo de un vector es una operación lenta, porque en cada paso, todos los elementos del vector deben desplazarse hacia abajo en un lugar. Mejor sería recorrer el vector liberando todo (luego clear() el vector, aunque como Mike dice que no es necesario si el vector es miembro de un objeto que está siendo destruido).

+0

+1 para el bucle primero, borrar después. –

11

El problema es que está tratando de usar un iterador mientras usa la función borrar(). borrar(), push_back(), insert() y otras funciones modificadoras invalidan iteradores en STL.

sólo tiene que utilizar la función clear():

City::~City() 
{ 
    m_basesVector.clear(); 
} 
+0

Bueno, si invalidan los iteradores depende del tipo de contenedor. – mkb

+0

@Matt, no depende del uso de vectores. – riwalk

+1

@Matt: 'erase' siempre invalidará los iteradores que se refieren al elemento borrado. –

0

iteradores vectoriales incrementable, pero si elimina elementos, el contenido de vectores son modificados y por lo tanto el iterador no es válido.

Por lo tanto, si elimina objetos, debe usar el valor de retorno de erase() que le proporciona el siguiente iterador válido.

1

Cualquier iterador que apunta al elemento eliminado o a los elementos después del que se elimina se invalida cuando se llama al método de borrado del vector. El método de borrado devuelve un iterador válido que apunta al siguiente elemento en el vector. Debe usar ese iterador para continuar su bucle & sin incrementar el iterador invalidado. También puede usar el método claro para eliminar todos los elementos en el vector. Sin embargo, deberá recordar desasignar explícitamente cualquier memoria asignada para los elementos.

3

Si usted está tratando de liberar a los datos en el vector, hacer esto:

for (std::vector<Base*>::iterator it = v.begin(), e = b.end(); it != e; ++it) 
    delete *it; 
1

Este código fugas todos los contenidos del vector - usted tiene que delete *deleteIterator en el circuito también. Puede evitar todo esto usando Base en lugar de Base* como el contenido vector, luego clear() los destruirá por usted. O use boost::ptr_vector que automatiza la destrucción si necesita punteros sin procesar.

Llamar erase() en una iteración hacia adelante como esta puede ser muy costoso si el vector es grande, ya que cada elemento sobre la posición actual tiene que moverse hacia abajo para garantizar que los elementos permanezcan contiguos. Evite el borrado manual del tipo que propone, por esta y otras razones.

2

Publicando esto solo en caso de que alguien más tenga este problema e intente con esta solución preguntándose por qué no está funcionando aquí hay una solución/explicación real.

@Steve Jessop - Su código es defectuoso y usted también lo ha escrito aquí ... (También he editado su publicación para solucionar el problema tan pronto como se aprueba, se solucionará en la publicación original)

http://techsoftcomputing.com/faq/3779252.html

no veo cómo esto es una "solución" al problema cuando se crea un tema nuevo, haciendo un bucle sin fin debe haber un deleteIterator ++ dentro del bucle while para que llegue realmente a el final del vector.

También me encontré con este problema y mi solución estaba dentro del ciclo while comprobando si el iterador era igual al final o si el tamaño del vector era 0 y se rompía antes de intentar incrementar el iterador.

Ej.

std::vector<RankPlayer*>::iterator Rank_IT = CurrentPlayers.begin(); 

    while (Rank_IT != CurrentPlayers.end()) 
    {  
     RankPlayer* SelPlayer = (*Rank_IT); 

     if(strstr(SelPlayer->GamerTag, this->GamerTag) != NULL) 
     { 

      delete[] SelPlayer->PlayerData; 
      delete[] SelPlayer; 
      Rank_IT = CurrentPlayers.erase(Rank_IT); 
     } 

     if(Rank_IT == CurrentPlayers.end() || CurrentPlayers.size() == 0) 
     { 
      break; 
     } 
      ++Rank_IT; 
    } 
+0

Esta es una respuesta y una diatriba, así como un comentario.Recomiendo encarecidamente que no sea una farsa y comentario, o se eliminará rápidamente. –

2

Esto no es relevante para el problema original publicado anteriormente, pero la búsqueda de Google en el error me lleva a esta página, así que estoy publicando aquí para que nadie vea.

Me encontré con este mensaje de error recientemente y todas las líneas de códigos prestados (no hubo 'borrar' o nada por el estilo, el vector fue meramente leído).

Finalmente, me di cuenta de que hay un problema con los bucles anidados.

Por ejemplo, considere algo como esto: - (!)

`for (it=begin(); it!=end();i++) 
{ 
    for (; it!=end();i++) 
    { 
    } 
}` 

Cuando haya terminado con el bucle anidado, se incrementará el iterador y luego, el bucle padres se incrementará de nuevo, en última instancia, hacer el paso del iterador sobre el final(). Es decir. sería "end() + 1" si existiera tal cosa. En consecuencia, el bucle padre arroja este error en la siguiente comprobación.

Para evitar esto, terminé insertar esta línea después del bucle niño:

`if (it == vStringList.end()) --it;` 

sucio, pero funciona: D

Sé que puede ser obvio para algunos, pero no tengo estado rascándome la cabeza por esto por un tiempo, lol

Cuestiones relacionadas