Secondo lo standard C++, chiamare push_back()
su un vettore invalida l'iteratore se la nuova dimensione del vettore cresce oltre la sua capacità, ma su un elenco non invalida mai gli iteratori. Ora considerare i seguenti frammenti di codice:semantica di end() iteratore per vettore e lista
1.
vector<int> v{1,2,3};
v.reserve(100);
for (int i: v) {
v.push_back(i);
}
2.
list<int> l{1,2,3};
for (int i: l) {
l.push_back(i);
}
ho provato con gcc 4.8 e ha scoperto che il codice 1 finiture con v
essere {1,2,3,1,2,3}
, ma il codice 2 piste in un ciclo infinito. La spiegazione mi sembra abbastanza semplice: l'iteratore end()
di vector
punta a una posizione di memoria e, dal it is only evaluated once during a range based for loop, si ferma quando raggiunge il terzo elemento del vettore. D'altra parte, list
probabilmente ha un qualche tipo di token nullo come iteratore finale, che viene sempre posizionato dopo l'ultimo elemento, quindi il ciclo non lo raggiungerà mai.
Mentre i risultati sembrano semplici, la mia domanda è: cosa dice lo standard a riguardo? Si suppone che sia così in tutte le implementazioni di libreria standard, o questo comportamento non è definito? Cosa devo aspettarmi quando si scrive un ciclo che può chiamare push_back()
in un contenitore di questo tipo (che di solito preferisco evitare comunque)?
Immagino che lo Standard non abbia molto da dire a riguardo. È permesso, è legale, è solo un ciclo infinito –
@AndyProwl Penso che lo standard abbia qualcosa da dire: è necessario che sia un ciclo infinito. (Se non è un ciclo infinito con 'vector', è perché c'è un comportamento indefinito, quindi qualsiasi cosa l'implementazione è legale.) –
@JamesKanze: Beh, è lo stesso che intendevo dire. Il PO ha scritto un ciclo infinito legale, non c'è nulla che lo standard abbia da dire su quella particolare situazione (parlando ovviamente dell'esempio della lista). –