Il codice presenta un comportamento indefinito, ma è difficile e tende a essere catturato solo nelle build di debug.
Quando si esegue uno v.push_back
, tutti gli iteratori vengono invalidati se le dimensioni superano la capacità. Lo eviti con una riserva.
Tuttavia, anche se non si aumenta la capacità, l'iteratore passato-end viene comunque invalidato. In generale, le regole di invalidazione iteratore non distinguono tra "il valore dell'iteratore" sarebbe spazzatura/fare riferimento a un oggetto diverso "e" la posizione dell'iteratore "non è più valida". Quando si verifica uno dei due, l'iteratore viene semplicemente ritenuto non valido. Poiché l'iteratore finale non è più l'iteratore finale (si passa dal riferimento al nulla, al riferimento a qualcosa, in quasi tutte le implementazioni), lo standard afferma semplicemente che è invalidato.
Questo codice:
for (auto e: v)
v.push_back(e*e);
si espande a circa:
{
auto && __range = v;
for (auto __begin = v.begin(),
__end = v.end();
__begin != __end;
++__begin
)
{
auto e = *__begin;
v.push_back(e*e);
}
}
la chiamata v.push_back
invalida la __end
iteratore, che viene poi confrontato, e la build di debug correttamente bandiere il comportamento non definito come problema. Gli iteratori di debug MSVC sono piuttosto accurati con le regole di invalidazione.
La versione di rilascio esegue un comportamento indefinito e poiché il vettore iteratore è fondamentalmente un involucro sottile attorno a un puntatore e il puntatore all'elemento passato-fine diventa il puntatore all'ultimo elemento dopo un push back senza una capacità overflow, "funziona".
È un comportamento non definito, potrebbe funzionare e potrebbe non esserlo. Nella build di debug non funziona. –
Per quanto riguarda il titolo, potrebbe applicarsi a una gamma così ampia di domande. Dovresti considerare di trovare un titolo che corrisponda strettamente al contenuto della domanda. Ad esempio, forse qualcosa del tipo "È legale aggiungere elementi a un vettore preallocato in un ciclo basato su intervalli su quel vettore?" Lascerò a te scegliere ciò che ritieni più ragionevole. – chris
@chris Hai ragione riguardo al titolo e l'ho modificato. La ragione per cui non sono andato con un titolo simile in primo luogo è puramente politico.Ho trovato che i SO redattori sono troppo felici nel segnalare le domande come duplicate e ignorano qualsiasi argomento futuro in contrario. Volevo aggirarlo. –