2010-09-23 19 views
19

Sto cercando di eliminare il contenuto del vettore e sto ricevendo un errore - l'iteratore vettoriale non è incrementabile, perché è così?Perché questo iteratore vettoriale non è incrementabile?

Questo è il mio distruttore:

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

grazie.

+5

Supponendo che 'm_basesVector' sia un membro di' City', non è necessario cancellarne gli elementi; il suo distruttore sta per farlo per te. –

+3

Sei consapevole che questo non eliminerà gli oggetti puntati dai puntatori. Dovresti chiamare 'delete deleteIterator; 'per ottenerlo (se è quello che vuoi). Comunque, in questo caso, dovresti preferire 'boost :: ptr_vector'. –

+0

Vedere [lì] (http://stackoverflow.com/questions/307082/). – Wok

risposta

41

erase invalida l'iteratore. Non puoi più usarlo. Fortunatamente per voi, restituisce un iteratore che è possibile utilizzare:

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

Oppure:

m_basesVector.clear(); 

Sei responsabile di liberare la memoria a cui si riferisce i puntatori nel vettore? Se è questa la ragione per cui stai iterando (e il tuo programma reale ha più codice che non hai mostrato, che libera quegli oggetti nel loop), ricorda che cancellare da un vettore è un'operazione lenta, perché ad ogni passo, tutti gli elementi del vettore devono essere spostati verso il basso in un punto. Meglio sarebbe fare un loop sul vettore liberando tutto (quindi il vettore clear(), anche se Mike dice che non è necessario se il vettore è un membro di un oggetto che viene distrutto).

+0

+1 per ciclo prima, chiaro dopo. –

11

Il problema è che si sta tentando di utilizzare un iteratore mentre si utilizza la funzione cancella(). cancella(), push_back(), insert() e altre funzioni di modifica invalidano gli iteratori in AWL.

basta usare la funzione di cancellazione():

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

Bene, se invalidano gli iteratori dipende dal tipo di contenitore. – mkb

+0

@Matt, non dipende dall'uso dei vettori. – riwalk

+1

@ Matt: 'erase' sempre invalidare iteratori che fanno riferimento all'elemento cancellati. –

0

iteratori vettoriali sono incrementabile, ma se si eliminano gli elementi, i contenuti vettoriali vengono modificati e quindi l'iteratore non è valido.

Quindi, se si eliminano oggetti, è necessario utilizzare il valore di ritorno di erase() che fornisce il successivo iteratore valido.

1

Qualsiasi iteratore che punta all'elemento eliminato o agli elementi dopo quello eliminato viene invalidato quando viene chiamato il metodo di cancellazione del vettore. Il metodo di cancellazione restituisce un iteratore valido che punta all'elemento successivo nel vettore. Si dovrebbe usare quell'iteratore per continuare il ciclo & senza incrementare l'iteratore invalidato. Puoi anche usare il metodo clear per rimuovere tutti gli elementi nel vettore. Tuttavia, sarà necessario ricordare di deselezionare esplicitamente qualsiasi memoria allocata per gli elementi.

3

Se si sta tentando di liberare i dati nel vettore, fare questo:

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

Questo codice trapela tutto il contenuto del vettore - dovete delete *deleteIterator nel ciclo troppo. È possibile evitare tutto ciò utilizzando Base anziché Base* come contenuto vector, quindi clear() li distruggerà per te. Oppure usa boost::ptr_vector che automatizza la distruzione se hai bisogno di puntatori grezzi.

Chiamare erase() in una iterazione diretta come questa può essere molto costoso se lo vector è grande, poiché ogni elemento sopra la posizione corrente deve essere spostato verso il basso per garantire che gli elementi rimangano contigui. Evita la cancellazione manuale del tipo che proponi, per questo e altri motivi.

2

questo distacco solo in caso chiunque altro ha questo problema e tentativi di questa soluzione chiedendo perché non funziona, ecco una soluzione/spiegazione reale.

@Steve Jessop - Il tuo codice è imperfetto e lo hai anche scritto qui ... (Ho anche modificato il suo post per risolvere il problema non appena approvato, verrà corretto nel post originale)

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

non vedo come questo sia una "soluzione" al problema quando si crea un problema nuovo, facendo un ciclo infinito ci dovrebbe essere un deleteIterator ++ all'interno del ciclo while in modo che raggiunga realtà la fine del vettore.

Inoltre, ho riscontrato questo problema e la mia soluzione era all'interno del ciclo while per verificare se l'iteratore era uguale alla fine o se la dimensione del vettore era 0 e si interrompeva prima di tentare di incrementare l'iteratore.

Es.

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

Questa è una risposta e uno sfogo, oltre a un commento.Suggerisco caldamente di renderlo meno rant e commentare, o verrà rimosso rapidamente. –

2

Questo non è pertinente al problema originale postato sopra, ma di ricerca di Google sull'errore mi porta a questa pagina in modo sto inviando qui per chiunque di vedere.

mi sono imbattuto in questo messaggio di errore di recente e tutte le linee di codice controllato fuori (non c'era 'Erase' o qualcosa di simile, il vettore è stato solo lettura).

Alla fine, mi sono reso conto che c'è un problema con cicli annidati.

Ad esempio, si consideri qualcosa di simile: - (!)

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

Quando si è fatto con il ciclo nidificato, si incrementerà l'iteratore e poi, il ciclo genitore verrà incrementato di nuovo, in ultima analisi, rendendo il passo iteratore alla fine(). Cioè sarebbe "end() + 1" se ci fosse una cosa del genere. Di conseguenza, il ciclo genitore tiri questo errore al momento del check successivo.

Per aggirare il problema, ho finito per inserto questa linea dopo il ciclo bambino:

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

sporco, ma funziona: D

So che può essere ovvio per alcuni, ma ho mi sono grattato sopra la testa per un po ', lol