2012-05-29 2 views
13

Quanto segue fornisce risultati definiti in termini di standard C++?Comportamento di std :: list: begin() quando l'elenco è vuoto

std::list<int> myList; 
std::list<int>::iterator myIter = myList.begin(); // any issues? 
myList.push_back(123); 
myIter++;         // will myIter point to the 123 I pushed? 

Posso testarlo sul compilatore che sto usando ... ma vorrei una risposta più definitiva.

+0

Penso che questa sia una buona domanda perché mi ha fatto pensare, hmm, in realtà. È una lista ... forse potrebbe funzionare ... (Ovviamente non lo è) – jcoder

risposta

18

Tutti iteratore standard ed container si comportano allo stesso a questo proposito:

§23.2.1 [container.requirements.general] p6

begin() retu rns un iteratore che si riferisce al primo elemento nel contenitore. end() restituisce un iteratore che rappresenta il valore passato-finale per il contenitore. Se il contenitore è vuoto, quindi begin() == end();

E tavolo 107 in §24.2.3 [input.iterators] richieste che come condizione preliminare per ++it, it devono essere dereferenceable, che non è il caso per iteratori past-the-end (ad esempio, quello che si ottiene da end()), come tale Stai calpestando il temuto dominio del comportamento indefinito.

+0

quindi se fosse 'myIter -', punterà al valore spinto? – balki

4
std::list<int> myList; 
std::list<int> myIter = myList.begin(); 

L'iteratore ha lo stesso valore come se si stesse inizializzandolo con myList.end(). L'iteratore è inizializzato alla posizione di fine passato. Anche dopo aver premuto un elemento nella lista, l'iteratore punta ancora uno-oltre-la-fine. Se lo si incrementa, si invoca un comportamento non definito.

UPDATE:

Ad esempio, se si compila il frammento con GCC con -D_GLIBCXX_DEBUG, l'eseguibile risultante abortire: tipi

/usr/include/c++/4.6/debug/safe_iterator.h:236:error: attempt to increment 
    a past-the-end iterator. 

Objects involved in the operation: 
iterator "this" @ 0x0x7fffc9548fb0 { 
type = N11__gnu_debug14_Safe_iteratorINSt9__cxx199814_List_iteratorIiEENSt7__debug4listIiSaIiEEEEE (mutable iterator); 
    state = past-the-end; 
    references sequence with type `NSt7__debug4listIiSaIiEEE' @ 0x0x7fffc9548fb0 
} 
zsh: abort (core dumped) ./listiter 
+0

... eccetto che quando hai una lista circolare, one-past-the-end potrebbe darti un legittimo punto di inizio da alcuni definizioni. Quindi sei assolutamente sicuro ... o fai una supposizione istruita? – omatai

+5

@omatai: 'std :: list <>' non è circolare. – wilx

+0

Ah - sì - nella mia mente stanca, ho confuso "doppiamente collegato" con "circolare" perché ogni volta che usavo (anni fa) fare una lista doppiamente collegata, aveva sempre una sola testa/coda che completava un " cerchio". D'oh! Devo andare a casa ... – omatai