2013-02-01 16 views
10

Controllare questo codice:std :: list :: clear invalidate std :: list :: end iterator?

#include "stdafx.h" 
#include <list> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::list<int> mylist; 
    mylist.push_back(1); 
    std::list<int>::iterator i = mylist.end(); 
    if(i == mylist.end()) 
     printf("end is end\n"); 

    mylist.clear(); 
    if(i == mylist.end()) 
     printf("never get here because Microsoft seems to " 
       "think the iterator is no longer safe.\n"); 

    return 0; 
} 

Ora, secondo cplusplus.com questo non dovrebbe essere un problema, e in modalità di rilascio, penso che questo va bene e non causa problemi in realtà, ma il debugging diventa impossibile come questo balbetta senza lasciarmi continuare. Qualche indicazione?

+0

Interessante. Ho pensato che anche '.end' sia stato invalidato, ma l'articolo dice il contrario. È interessante, che http://ideone.com/Y338N8 lo esegue come previsto. +1 –

+0

Questo ha perfettamente senso poiché il codice che sto provando a portare su Windows è stato scritto per MacOS e Linux. Entrambi gestiscono GCC, come fa l'ideone. Immagino che questo sia un bug della biblioteca. –

risposta

10

Altre risposte sottolineano che, in generale, non è possibile fare affidamento sull'iterazione iteratore di un contenitore che rimane valido quando il contenitore viene cancellato. Tuttavia, l'iteratore past-the-end di un elenco dovrebbe infatti rimanere valida:

C++ 11 23.3.5.4/3 Effetti: invalida solo le Iteratori e riferimenti agli elementi cancellati.

L'iteratore del passato non fa riferimento a nessun elemento, quindi non dovrebbe essere invalidato.

+0

+1, rimossa la mia risposta. Mentre ricordo dalle precedenti conversazioni che l'utilizzo di una sentinella allocata dinamicamente è esplicitamente supportata dallo standard, ciò non significa che 'clear()' debba rilasciarlo. Basta controllare la nostra implementazione e 'clear()' è implementato come 'erase (begin(), end())' e non invalida gli iteratori 'end()'. Questo dovrebbe essere segnalato a Microsoft come un bug nella loro implementazione. –

+2

Grazie, Mike e @ DavidRodríguez-dribeas. Sì, questo è un bug nell'implementazione di 'std :: list' di Visual C++ 2012. È una regressione da Visual C++ 2010. Si noti che 'cancella' è rotto in modo simile. Ho controllato una correzione per questo bug alcuni mesi fa e la correzione apparirà nella prossima versione rilasciata della libreria standard di Visual C++. La correzione corregge sia 'cancella' che' cancella'. (Questo bug è stato segnalato da un cliente, ma non tramite Microsoft Connect, quindi non ho un collegamento a cui posso riferirti.) –

+1

Segnalato a Microsoft, risolto ma solo in VS2013: http://connect.microsoft. com/VisualStudio/retroazione/dettagli/808.659/debug-mode-invalida STD-list-t-erase-in-fine-iteratore – Macker

-2

Questo non è valido. Gli iteratori sono validi solo nel contenitore di stato corrente. Dopo aver aggiunto o rimosso elementi, l'iteratore non è più valido.

L'articolo collegato non dice che quello che stai facendo è valido. Ottengono un nuovo iteratore dopo la cancellazione.

Il motivo per cui non viene visualizzato nel codice di rilascio è perché il debug che preleva il problema è disabilitato.

+0

E ancora una volta: Secondo il link nella domanda: "Tutti gli iteratori, i riferimenti e i puntatori relativi a questo contenitore sono invalidati, eccetto gli iteratori finali." –

+0

@meh: No, hai torto, l'iteratore di fine * può * essere invalidato –

+3

"Dopo aver aggiunto o rimosso elementi, l'iteratore non è più valido." Non è vero in generale; ogni contenitore ha le sue regole di invalidazione e gli iteratori di lista rimangono validi finché l'elemento a cui si riferiscono è ancora in una lista. –

4

Da C++ 11, (esigenze contenitive sequenza) Tabella 100:

clear() [...] può invalidare l'iteratore dopo-the-end.

E std::list è naturalmente un modello contenitore di sequenza (23.3.5.1/2):

Un elenco soddisfa tutti i requisiti di un contenitore, di un contenitore reversibile (proposta in due tabelle in 23.2), di un contenitore di sequenza, inclusi la maggior parte dei requisiti del contenitore sequenza opzionale (23.2.3) e di un contenitore che riconosce gli allocatori (Tabella 99). Le eccezioni sono l'operatore [] e le funzioni membro, che non sono fornite. Le descrizioni sono fornite qui solo per le operazioni sulla lista che non sono descritte in una di queste tabelle o per operazioni in cui sono disponibili ulteriori informazioni semantiche.

+0

Per aggiungere a questo: l'ender iterator è un valore singolare e la maggior parte dei contenitori di base dei nodi che garantiscono la stabilità degli iteratori forniscono questa garanzia solo per valori non singolari. –

+1

Credo che dovrebbe essere letto come "ci sono contenitori per i quali invalida iteratori e contenitori per i quali non funziona". Altrimenti, sarebbe una specifica in conflitto –

+1

Ma la specifica specifica dell'elenco, 23.3.5.4/3, dice "Invalida ** solo ** gli iteratori e i riferimenti agli elementi cancellati". –

Problemi correlati