Gültigkeit von Iteratoren bei zwischenzeitlichem Hinzufügen
-
Hallo zusammen,
ich hab hier mal nen Beispiel gepostet. Hier verwende ich einen
Iterator auf einem std::vector, füge neue Elemente hinzu und arbeite
dann mit dem Iterator weiter. Es funktioniert allerdings nicht, da der
std::vector sich irgendwann neuen Speicher alloziiert und der Inhalt
nun woanders liegt und der Iterator auf dem vorherigen Bereich weiterarbeitet.#include <iostream> #include <vector> #include <list> int main(int argc, char *argv[]){ std::vector<int> vec; for(int i=0; i<10; ++i){ vec.push_back(i); } std::vector<int>::const_iterator it = vec.begin(); for(int i=0; i<5; ++i){ int j = *it; std::cout << j << std::endl; ++it; } for(int i=10; i<1000; ++i){ vec.push_back(i); } for(;it!=vec.end(); ++it){ std::cout << *it << std::endl; } }Ich finde es auch sehr verständlich, warum das nicht geht.
Meine Intuition sagt mir, dass es bei einer std::list klappt, da es sich
ja um eine Verkettete Liste handelt. Es scheint auch zu funktionieren, aber
kann ich mich darauf verlassen oder hab ich unter Umständen
irgendwas zu befürchten?Wo ich den Beitrag gerade schreibe:
Darf ich mir aus genau diesem Grund auch keine Referenz auf ein Objekt
in einem Vektor dauerhaft halten?Gruß,
*Cpp-Anfänger*
-
Die Referenz die ich nutze sagt zum Einfügen in lists:
all of the previously obtained iterators and references remain valid after the insertion and refer to the same elements they were referring before.
Und ja, Referenzen in einen vector werden genauso wie Iteratoren ungültig, sobald eine Einfügeoperation ein umkopieren der Inhalte des vectors nötig macht.
-
bei list ist dir garantiert, dass das einfügen keine iteratoren und/oder referenzen invalidiert, das löschen nur den jeweiligen iterator, der auf das zu löschende element zeigt.
für vector ist das nur garantiert, wenn die anzahl der neuen elemente seine capacity vor dem einfügen nicht überschreitet. das heißt aber auch, dass deine iteratoren gültig bleiben, wenn du vor der initialisierung des iterators
vec.reserve (vec.size() + 1000); std::vector<int>::const_iterator it = vec.begin(); //...einfügst, wird dir auch nichts passieren.
/edit: bei vector natürlich nur für einfügeoperationen und auch nur am ende des vectors garantiert.
-
Vielen Dank für eure prägnanten Erklärungen.
Bisher hab ich Elemente immer mit
list.push_back(i);ans Ende einer Liste angehängt.
Hier steht sowas in dieser Referenz nicht
explizit bei.
In Zukunft werde ich wohl eherlist.insert(list.end(),i);benutzen. Sicher ist sicher

An di Möglichkeit der vorzeitigen Speicherreservierung für
std::vectot hab ich auch gedacht, aber danke für die definitive
Aussage.Ich wünsche euch noch einen schönen Heiligen Abend.