Heim > Backend-Entwicklung > C++ > Wie lösche ich Elemente aus einem std::vector während der Iteration mit einer bereichsbasierten For-Schleife sicher?

Wie lösche ich Elemente aus einem std::vector während der Iteration mit einer bereichsbasierten For-Schleife sicher?

Susan Sarandon
Freigeben: 2024-11-03 17:09:03
Original
930 Leute haben es durchsucht

How to Safely Erase Elements from a std::vector During Iteration with a Range-Based For Loop?

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
    }

}
Nach dem Login kopieren

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;
    }
}
Nach dem Login kopieren

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());
Nach dem Login kopieren

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&amp; 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());
Nach dem Login kopieren

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!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage