BeRsErKeR hat geschrieben:Gibt es einen speziellen Grund dafür, dass du den Iterator vor der Bedingung dekrementierst? Wenn ich nicht gerade Tomaten auf den Augen habe, ist das völlig äquivalent zu:
Code: Alles auswählen
for (auto iter = mListe.end(); iter != mListe.begin(); )
{
if (eineBedingung(*--iter))
iter = mListe.erase(iter);
}
Ja, denn es gibt keinen Zusammenhang zwischen Bedingung und Iterator. Mit dieser Verkürzung versteckst du den Dekrement unsinnig, im schlimmsten Fall geht er bei Änderung der Bedingung versehentlich verloren, wird bei Erweiterung der Bedingung dupliziert oder verschwindet irgendwann in einer Short Circuit Evaluation. Vor der Bedingung ist klar, dass der Dekrement
unbedingt am Anfang jeder Iteration durchgeführt wird und die Bedingung lässt sich jederzeit problemlos ändern.
BeRsErKeR hat geschrieben:Eine kleine Anmerkung noch. Ich finde es angenehmer die globalen Funktionen std::begin und std::end zu verwenden. Das hat den Vorteil, dass man keine Code-Änderungen benötigt falls aus der std::list mal ein Array wird. Ist nicht immer sinnvoll, aber ich wollte mal drauf hinweisen.
Stimme ich prinzipiell zu, aber da die Funktionen im
<iterator>-Header liegen, der in der MS-Implementierung ungefragt den schlimmsten Teil der STL nach sich zieht, bin ich minimalistisch geworden. :evil: Weiterhin gibt es da ein konzeptuelles Problem, du solltest die Funktionen nämlich dann ohne
std::-Qualifizierung aufrufen, d.h. du brauchst entweder global ein
using std::begin; using std::end; oder musst das vor jedem Aufruf einfügen (und das
nur für Array-Kompatibilität!). Leider wie so oft seitens STL ein winziges Bisschen zu kurz gedacht.
Was lernen wir aus dieser Missorganisation: Häufig genutzte Funktionalität besser nach Nutzungsfrequenz als nach artifiziellen Modulen in Headers einordnen; insbesondere so modularisieren, dass häufig genutzte Funktionalität nicht durch ungeschickte Modulzuordnung indirekt von selten genutzter Funktionalität abhängt.