2012-04-30 13 views
5

Escribí este pequeño código solo para ver cómo un iterador realmente se invalida y no apunta a la ubicación cambiada de un vector una vez que se alcanza su capacidad.¿Por qué C++ no se ocupa de los iteradores cuando la inserción se realiza en un vector una vez que se alcanza la capacidad?

Aquí el tamaño del vector y la capacidad son inicialmente 5. Después de eso inserté algunos otros elementos en el vector y no reinicio mi iterador para apuntar a myvector.begin(). Esto condujo a un valor no deseado de 49 en mi salida después de maximum size of vector is : 1073741823 al imprimir elementos del vector nuevamente.

Mi pregunta es por qué C++ no vuelve a hacer iterador de puntos a un myvector.begin() válido después de que todos los elementos se hayan copiado en una nueva ubicación.
Esto también puede llevar a un comportamiento que puede ser difícil de depurar. Sé que una forma segura de trabajar sería siempre reiniciar el iterador justo antes de usarlo.

#include<iostream> 
    #include<vector> 
    #include<stdio.h> 

    using namespace std; 

    int main() 
    { 
    vector<int> myvector; 
    vector<int>::iterator it; 
    int myarray[]= {100,200,300,400}; 
    myvector.insert(it,500); 
    it=myvector.begin(); 
    myvector.insert(it,myarray,myarray+4); 
    it=myvector.begin(); 
    for(;it!=myvector.end();++it) 
    cout <<*it<<endl; 
    cout <<"size of vector is :" << myvector.size() <<"\n"; 
    cout <<"capacity of vector is : " << myvector.capacity()<<"\n"; 
    cout <<"maximum size of vector is : " << myvector.max_size()<<"\n"; 
    myvector.push_back(600); 
    for(;it!=myvector.end();++it) 
    cout <<*it<<endl; 
    } 
    Output of program :- 
    100 
    200 
    300 
    400 
    500 
    size of vector is :5 
    capacity of vector is : 5 
    maximum size of vector is : 1073741823 
    49 
    100 
    200 
    300 
    400 
    500 
    600 
+0

[con 'std :: vector' cualquier cosa que cambie el tamaño invalida los iteradores anteriores] (http://stackoverflow.com/a/6438087/168175) – Flexo

+1

@awoodland parece saber eso, creo que está preguntando * por qué * esto está ocurriendo. –

+1

Cada contenedor de STL ofrece ciertas garantías con respecto a la validez de sus iteradores. Vale la pena entender cuándo los iteradores son invalidados para un contenedor dado. Ciertamente no desea siempre restablecer a un nuevo 'begin()' 'just in case'. Consulte aquí para obtener información sobre el 'vector' - http://www.sgi.com/tech/stl/Vector.html –

Respuesta

9

Porque no es práctico, y probablemente imposible.

se supone que el vector de mantener una lista de todos los sus iteradores y las modifican todo de ellos tan pronto como un método invalide-activación se llama?

+0

No se puede asignar un espacio que contenga la dirección de myvector.begin() y todos los iteradores apuntan a esa ubicación y luego desde allí a la dirección original o posición inicial del vector.Y esta dirección que contiene la ubicación fija del vector se modifica a medida que se asigna un nuevo espacio para el vector. ¿Tendrán muchos gastos generales? No soy tan experto, así que lo pregunto. – Invictus

+1

@Ritesh sería una gran cantidad de gastos generales sin ninguna ganancia particular si tiene muchos iteradores. No es solo comienzo y fin, fíjate, y no es necesariamente solo uno de cada uno. –

+1

@Ritesh: siempre puedes crear un contenedor con iteradores que lo haga, pero dado que 'std :: list' existe, que no se invalida cuando crece, parece que no vale la pena. – Flexo

3

Probablemente porque el vector debería hacer un seguimiento de una lista de todos sus iteradores y notificarlos a todos cuando se vuelvan inválidos. Esto introduciría bastante sobrecarga. Todas las operaciones de los contenedores STL tienen reglas de invalidación muy bien especificadas, solo tiene que seguirlas como programador.

Tenga en cuenta que, según el estándar, no puede confiar en que los iteradores vector sean válidos después de la inserción o eliminación. Que todavía funcionó para usted hasta que el cambio de tamaño es un detalle de implementación.

4

El iterador no está vinculado al vector de ninguna manera significativa (¿cómo podría implementarse como un puntero si fuera?). El vector no sabe sobre el iterador. Es su trabajo no usar un iterador inválido.

Así que propones agregar un montón de complejidad a la clase de vector para ... ¿con qué propósito exactamente? ¿Cómo resuelve esto los problemas en el mundo real donde sabemos que hacer tal cosa es una mala idea?

1

El STL no intentó implementar todos los contenedores posibles. Si bien el diseño de su contenedor es ciertamente posible, simplemente no está incluido. std::vector<T> parece similar, pero intenta ser una matriz mejor que T[] con poca sobrecarga. Ese objetivo no es directamente compatible con el tuyo.

Afortunadamente, el diseño de STL es modular, por lo que incluso si escribió su propio contenedor para actuar así, puede reutilizar todos los algoritmos de STL, así como los algoritmos compatibles con STL (por ejemplo, los de refuerzo).

Cuestiones relacionadas