Der beste Weg, um in situ ein Element löschen

stimmen
2

Ich habe eine Reihe von Objekten, die ich durch laufen, aber ich während der Iteration kann vorsehen, dass eine (oder mehr) diese Objekte nun gelöscht werden müssen.

Mein Code sieht wie folgt aus:

if( ! m_Container.empty() )
    {
        for(  typedefedcontainer::iterator it = m_Container.begin();
              it != m_Container.end(); 
              ++it  )
        {
            if( ! ( SomeFunction( (*it), test, TEST!, false ))  )
            {
            // If function returns false, delete object.
                m_Container.erase( it );
                AsyncResponseStore::iterator it = m_asyncResponses.begin();
            }

        }


    }

Aber natürlich, wenn ich ein Objekt löschen bekomme ich einen Fehler: „Karte / set Iterator nicht inkrementierbarer“. Kann jemand einen besseren Weg, dies zu tun vorschlagen?

Siehe auch : Was passiert , wenn Sie erase () auf einem Kartenelement aufrufen , während von beginnen Iterieren zu beenden?

Veröffentlicht am 09/12/2008 um 17:09
quelle vom benutzer
In anderen Sprachen...                            


3 antworten

stimmen
6

Es hängt von dem Behälter. Die Liste Container unterstützt Löschen während der Enumeration durch einen neuen Iterator aus dem Löschverfahren zurückkehrt, die das nächste Element in der Liste steht. Karte unterstützt dies nicht.

Eine einfache Methode zur Karte ist die Elemente sammeln Sie in einer separaten Liste löschen möchten, und dann über diese Liste durchlaufen, wenn Sie fertig sind die Karte Verarbeitung der Produkte von der Karte zu löschen. Dies setzt voraus, dass Sie das Löschen verschieben können, bis die Iteration abgeschlossen hat. Wenn nicht, dann haben Sie keine andere Wahl, als den Neustart der Iteration für jede Löschung.

Beantwortet am 09/12/2008 um 17:18
quelle vom benutzer

stimmen
0

Feste durch:

for(  typedefedcontainer::iterator it = m_Container.begin();
      it != m_Container.end(); 
        )
{
    if( ! ( SomeFunction( (*it), "test", "TEST!", false ))  )
    {
    // If function returns false, delete object.
        m_Container.erase( it++ );
    }
    else
    { 
        ++i;
    } 

}

Wenn ein Element gelöscht wird, werden alle Zeiger auf sie für ungültig erklärt werden. Deshalb, indem Sie es ++ bekommen wir es um. Dank denen, die Vorschläge gepostet.

Beantwortet am 09/12/2008 um 17:30
quelle vom benutzer

stimmen
6

Wenn der Container unterstützt (was ich vermute, Ihnen nicht der Fall, aber die Frage Titel ist generisch, so kann dies, wenn Sie nicht für andere nützlich sein):

struct SomePredicate {
    bool operator()(typedefedcontainer::value_type thing) {
        return ! SomeFunction(thing, "test", "TEST", false);
    }
};

typedefedcontainer::iterator it;
it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate());
m_Container.erase(it, m_Container.end());

m_Container muss ein Löschbereich-Methode haben, die jede Sequenz oder assoziativ Behälter enthält. Es hat eine veränderbare Iterator haben, aber, und ich habe gerade bemerkt, dass ich die Fehlermeldung ursprünglich falsch verstanden: es heißt „Karte / set Iterator nicht inkrementierbarer“. Also ich denke, Ihr Container eine Karte oder ein Satz ist.

Beachten Sie, dass die letzten drei ein wirklich wunderbarer Einzeiler sein könnte, aber dieser Spielraum ist zu schmal, um es zu enthalten.

Auch dass SomePredicate könnte einen Konstruktor mit Parametern müssen die zusätzlichen Parameter Einefunktion zu speichern, da im wirklichen Leben Ich denke, sie sind nicht konstant.

Sie könnten tatsächlich von SomePredicate ganz loszuwerden, wenn Sie boost: bind die Funktors zu konstruieren. Ihr One-Liner wäre dann wirklich massiv sein.

[Edit: Rob Walker Noten korrekt in seiner Antwort eine Annahme, die ich hier machen und dass die Frage gibt nicht an, das ist, dass alle Lösch bis verschoben werden können, nachdem der iterate-and-Test durchgeführt wird. Wenn Einefunktion m_Container Zugriffe durch einen versteckten Weg (zB ein globales, oder weil Einefunktion ist eigentlich eine Member-Funktion von dieser), und die Ergebnisse sind abhängig von den Inhalt des Behälters, dann kann mein Code nicht äquivalent sein, um den Code des Fragestellers. Aber ich denke, mein Code ist die „es sei denn, es gibt einen Grund, nicht zu“ default.]

Beantwortet am 09/12/2008 um 17:39
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more