2012-04-30 11 views
5

Ho scritto questo piccolo codice solo per vedere come un iteratore viene effettivamente invalidato e non punta alla posizione modificata di un vettore dopo che è stata raggiunta la sua capacità.Perché C++ non si occupa degli iteratori quando l'inserimento viene eseguito in un vettore dopo aver raggiunto la capacità?

Qui le dimensioni del vettore e della capacità sono inizialmente 5. Dopo di che ho inserito alcuni altri elementi nel vettore e non reinizializza il mio iteratore in modo che punti a myvector.begin(). Ciò ha comportato un valore indesiderato di 49 nell'output dopo maximum size of vector is : 1073741823 quando si stampano di nuovo elementi vettoriali.

La mia domanda è perché C++ non rende nuovamente l'iteratore di punti a uno myvector.begin() valido dopo che tutti gli elementi sono stati copiati in una nuova posizione?
Ciò può anche portare a un comportamento che può essere difficile da eseguire il debug. So che un modo sicuro per lavorare sarebbe quello di reinizializzare sempre l'iteratore prima di 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' tutto ciò che cambia la dimensione invalida precedenti iteratori] (http://stackoverflow.com/a/6438087/168175) – Flexo

+1

@awoodland sembra sapere che, penso che stia chiedendo * perché * sta succedendo questo. –

+1

Ogni contenitore STL fornisce determinate garanzie sulla validità dei suoi iteratori. Vale la pena capire quando gli iteratori sono invalidati per un determinato contenitore. Certamente non vuoi reimpostare sempre su un nuovo 'begin()' 'nel caso'. Vedi qui per info re 'vector' - http://www.sgi.com/tech/stl/Vector.html –

risposta

9

Perché non è pratico e probabilmente impossibile.

è il vettore suppone di mantenere un elenco di tutti i suoi iteratori e modificarli tutte di loro, non appena un metodo invalide-triggering si chiama?

+0

non può essere assegnato uno spazio che contenga l'indirizzo di myvector.begin() e tutti gli iteratori puntino a quella posizione e quindi da lì all'indirizzo originale o posizione iniziale del vettore.E questo indirizzo che mantiene la posizione fissa del vettore può essere modificato man mano che il nuovo spazio viene assegnato al vettore ?. Avrà molti overhead? Non sono così esperto da chiederlo. – Invictus

+1

@Ritesh ci sarebbe un sacco di spese generali senza particolari guadagni se hai un sacco di iteratori. Non è solo l'inizio e la fine, bada bene, e non è necessariamente solo uno di ciascuno. –

+1

@Ritesh - si può sempre creare un contenitore con iteratori che lo faccia, ma dato che 'std :: list' esiste che non viene invalidato quando cresce che sembra non averne alcun valore. – Flexo

3

Presumibilmente perché il vettore dovrebbe tenere traccia di un elenco di tutti i suoi iteratori e notificarli tutti quando diventano non validi. Ciò introdurrebbe un sacco di spese generali. Le operazioni dei contenitori STL hanno tutte regole di invalidazione molto ben specificate, devi solo seguirle come programmatore.

Si noti che, come per lo standard, non è possibile fare affidamento su iteratori di vettori che sono validi a tutti dopo l'inserimento o la cancellazione. Che ha funzionato per te fino al ridimensionamento è un dettaglio di implementazione.

4

L'iteratore non è legato al vettore in alcun modo significativo (come potrebbe essere implementato come puntatore se lo fosse?). Il vettore non conosce l'iteratore. È tuo compito non utilizzare un iteratore non valido.

Quindi si propone di aggiungere una tonnellata di complessità alla classe vettoriale per ... quale scopo esattamente? In che modo questo risolve i problemi nel mondo reale dove sappiamo che fare una cosa del genere è una cattiva idea?

1

STL non ha provato a implementare tutti i possibili contenitori. Mentre il design del tuo contenitore è certamente possibile, non è incluso. std::vector<T> sembra simile, ma cerca di essere un array migliore di T[] con poco overhead. Questo obiettivo non è direttamente compatibile con il tuo.

Fortunatamente, il design STL è modulare, quindi anche se si è scritto il proprio contenitore per agire in questo modo, è ancora possibile riutilizzare tutti gli algoritmi STL, nonché gli algoritmi compatibili con STL (ad esempio quelli in boost).

Problemi correlati