std::list - element innerhalb eines iterators löschen
-
Hi,
ich iteriere durch eine std::list und überprüfe dabei die einzelnen Objekte. Als Ergebnis dieser Überprüfung müssen einige Elemente aus der Liste gelöscht werden. wenn ich das allerdings mit remove() noch innerhalb des iterator-for-next-Loops mache, dann fliegt mir das beim nächsten Element um die Ohren.
Also wie kann ich die Elemente dann sauber und innerhalb einer gerade bearbeiteten Liste löschen?
-
-
Schöne Antwort, passt nur nicht zur gestellten Frage. 6, setzen.
-
Siehe
http://www.cplusplus.com/reference/stl/list/erase/
(achte auf das, was die Funktion zurück gibt!)Oder nimm gleich:
http://www.cplusplus.com/reference/stl/list/remove_if/Wenn Du Code gezeigt hättest, hätte man Dich direkt auf einen Fehler hinweisen können. Denn das Löschen von einigen Listen-Elementen in einer Schleife ist möglich.
Wahrscheinlich sieht Dein Code so aus:
for (iter_t it = liste.begin(), it!=liste.end(); ++it) { if (bedingung) { liste.erase(it); } }Aber nach dem erase wird natürlich der Iterator ungültig! Deswegen muss man schreiben:
for (iter_t it = liste.begin(), it!=liste.end();) { if (bedingung) { it = liste.erase(it); } else { ++it; } }Das ++it habe ich aus derm for(...) rausgenommen.
Und das ist auch in etwa das, was bei std::list::remove_if passiert.
struct is_odd { bool operator()(int i) const {return i%2!=0;} }; : : list<int> iliste = ... iliste.remove_if(is_odd()); // alle ungeraden Zahlen entfernenkk
-
krümelkacker schrieb:
...
Aber nach dem erase wird natürlich der Iterator ungültig! Deswegen muss man schreiben:for (iter_t it = liste.begin(), it!=liste.end();) { if (bedingung) { it = liste.erase(it); } else { ++it; } }Das ++it habe ich aus derm for(...) rausgenommen.
...
kkdamit die iteration trotzdem noch drinne sethet in der for-schleife kannmanauch (wenn man platzgeil ist und so wenig wie zeilen schreiben will) folgendes schreiben:
for (iter_t it = liste.begin(), it!=liste.end();it++) { if (bedingung) it = liste.erase(it--); }ich würde es jetzt mal die Tango-Version des elementlöschens nennen (2 Schritte vor 1Schritt zurück ..
)
-
its_me_mario schrieb:
for (iter_t it = liste.begin(), it!=liste.end();it++) { if (bedingung) it = liste.erase(it--); }ich würde es jetzt mal die Tango-Version des elementlöschens nennen (2 Schritte vor 1 Schritt zurück ..
)Blöd nur, dass
it--beim ersten Element der Sequenz nicht erlaubt ist.- in dem Ausdruck, 2mal
itverändert wird, ohne dass ein Sequenzpunkt dazwischen ist (--> undefiniertes Verhalten).
-
its_me_mario schrieb:
damit die iteration trotzdem noch drinne sethet in der for-schleife kannmanauch (wenn man platzgeil ist und so wenig wie zeilen schreiben will) folgendes schreiben:
for (iter_t it = liste.begin(), it!=liste.end();it++) { if (bedingung) it = liste.erase(it--); }ich würde es jetzt mal die Tango-Version des elementlöschens nennen (2 Schritte vor 1Schritt zurück ..
)Was schief geht, wenn zufällig das erste Element gelöscht werden muss.
-
krümelkacker schrieb:
[*] in dem Ausdruck, 2mal
itverändert wird, ohne dass ein Sequenzpunkt dazwischen ist (--> undefiniertes Verhalten).Da ist ein Funktionsaufruf dazwischen, folglich auch ein Sequenzpunkt. Zudem sind list-Iteratoren sowieso keine einfachen Pointer, so dass das Dekrementieren zwangsläufig ebenso einen Funktionsaufruf darstellt.
-
I stand corrected.
1.9/16
When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all
function arguments (if any) which takes place before execution of any expressions or statements in the function body.There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function. ...