Elemente aus einem std::vector löschen, während mit einer bereichsbasierten For-Schleife iteriert wird
Über einen std::vector iterieren und entfernen Elemente, die einer bestimmten Bedingung entsprechen, können eine häufige Aufgabe bei der Programmierung sein. Allerdings stellt die standardmäßige bereichsbasierte For-Schleifensyntax eine Herausforderung dar, da der Versuch, ein Element während der Iteration zu löschen, den Iterator ungültig machen kann.
Das Problem beim Löschen innerhalb einer bereichsbasierten For-Schleife
Der folgende Codeausschnitt veranschaulicht das Problem:
for(iterator it = begin; it != end; ++it) { if(it->somecondition() ) { erase it } }
Während die Absicht darin besteht, Elemente zu entfernen, die sich treffen Aufgrund der Bedingung ist dieser Ansatz falsch. Wenn ein Element gelöscht wird, wird der Iterator ungültig. Das weitere Iterieren mit diesem Iterator führt zu undefiniertem Verhalten.
Lösung 1: Verwendung einer regulären For-Schleife mit expliziter Iteratormanipulation
Eine Lösung besteht darin, eine reguläre for-Schleife zu verwenden mit expliziter Iteratormanipulation:
for(iterator it = begin; it != end(container) /* !!! */;) { if (it->somecondition()) { it = vec.erase(it); // Returns the new iterator to continue from. } else { ++it; } }
Beachten Sie hier den entscheidenden Unterschied: Wir rufen end(container) explizit auf jede Iteration, um einen neuen Enditerator zu erhalten. Dies ist notwendig, da das Löschen eines Elements den ursprünglichen Iterator ungültig macht.
Lösung 2: Verwendung von std::remove_if und erase
Eine effizientere Alternative ist die Kombination von std:: remove_if und erase():
iterator it = std::remove_if(begin, end, pred); vec.erase(it, vec.end());
std::remove_if entfernt übereinstimmende Elemente ein angegebenes Prädikat, während erase() sie löscht. Dieser Ansatz reduziert die Zeitkomplexität von O(N2) in der ersten Lösung auf O(N).
Lösungsspezifisch für das bereitgestellte Beispiel
Im angegebenen Beispiel kann der folgende Code verwendet werden, um zeitgesteuerte Ereignisse zu entfernen, die einem bestimmten Widget zugeordnet sind:
class remove_by_caller { public: remove_by_caller(AguiWidgetBase* pWidget) : mWidget(pWidget) {} template <typename T> // for now a template bool operator()(const T& pX) const { return pX.getCaller() == mWidget; } private: AguiWidgetBase* mWidget; }; std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget)); timedEvents.erase(it, timedEvents.end());
Das obige ist der detaillierte Inhalt vonWie lösche ich Elemente aus einem std::vector während der Iteration mit einer bereichsbasierten For-Schleife sicher?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!