Wie löscht man Elemente aus std::set innerhalb einer Schleife?



  • ist der code von JimmydaMage nicht falsch?



  • Wusste ichs doch, Visual C++ meldet bei dem Code von JimmydaMage:

    map/set iterator not incrementable



  • JimmydaMage schrieb:

    Du hast das ein bisschen falsch verstanden ;). Nicht der Wert des Iterators wird ungültig (geht auch gar nicht, da nur eine Kopie an erase() übergeben wird), sondern das Objekt, auf das der Iterator verweist.

    Öhm. Nein!

    http://www.velocityreviews.com/forums/t277880-setltgteraseiterator-question.html



  • Ich benutze also das:

    schöner schrieb:

    if((*i)->irgendwas())
    {
        m.erase(i++);
    }
    else
    {
        ++i;
    }
    

    i++ macht eine Kopie des Iterators die zurückgegeben wird. Danach aber wird i intern inkrementiert und so zeigt er zu dem nächsten Element 🙂



  • Wieso benutzt du nicht einfach den Rückgabewert von erase()?

    Dinkumware Compleat Reference schrieb:

    set::erase
    iterator erase(iterator where);
    

    The [...] member function removes the element of the controlled sequence pointed to by where. [...] It returns an iterator that designates the first element remaining beyond any elements removed, or end() if no such element exists.

    Dann sieht das ganze ungefähr so aus:

    set<etwas> sc;
    //...
    for (set<etwas>::iterator it = sc.begin(), ie = sc.end(); it != ie;)
        if ((*i)->irgendwas())
        {
            it = sc.erase(it); //it wird auf das nächste Element gesetzt
        }
        else
        {
            ++it; //it wird so auch auf das nächste Element gesetzt
        }
    

    Felix



  • Phoemuex schrieb:

    Wieso benutzt du nicht einfach den Rückgabewert von erase()?

    Weil bei Set erase keinen Rückgabewert hat. Das ist laut Standard nicht vorgeschrieben.

    http://www.cppreference.com/cppset/erase.html



  • Ja, das habe ich auch erfahren davon:
    http://www.sgi.com/tech/stl/set.html



  • Um meinen etwas knappen Beitrag zum Them Nutze die Standardbibliothek zu vervollständigen hier etwas Code:

    set<etwas> sc;
    /*...*/
    struct testetwas {
      bool operator()(etwas const& e) {return e.irgendwas();}
    };
    std::remove_if(sc.begin(), sc.end(), testetwas());
    

    Da es ein etwas unbekannteres Feature von C++ ist hier eine kurze Erklärung: testetwas ist eine lokale Klasse, die direkt vor dem Aufruf von remove_if definiert werden kann, also innerhalb der Funktion, in der sie benutzt wird.



  • pumuckl schrieb:

    Um meinen etwas knappen Beitrag zum Them Nutze die Standardbibliothek zu vervollständigen hier etwas Code:

    set<etwas> sc;
    /*...*/
    struct testetwas {
      bool operator()(etwas const& e) {return e.irgendwas();}
    };
    std::remove_if(sc.begin(), sc.end(), testetwas());
    

    Da es ein etwas unbekannteres Feature von C++ ist hier eine kurze Erklärung: testetwas ist eine lokale Klasse, die direkt vor dem Aufruf von remove_if definiert werden kann, also innerhalb der Funktion, in der sie benutzt wird.

    Für mich ist das nicht unbekannt. Meinst du so:
    sc.erase(remove_if(sc.begin(), sc.end(), predikat), sc.end());?
    Bist du dir sicher, dass die remove_if Funktion mit set Iteratoren arbeiten kann?



  • khalderon schrieb:

    Meinst du so:
    sc.erase(remove_if(sc.begin(), sc.end(), predikat), sc.end());?

    Natürlich. Unachtsamkeit meinerseits.

    Bist du dir sicher, dass die remove_if Funktion mit set Iteratoren arbeiten kann?

    Wäre schon blöd, wenn STL-Algorithmen nicht mit STL-Iteratoren arbeiten könnten oder? 😉 Dafür sind sie ja gemacht, würde mich also mehr als verwundern wenns das nicht tut.



  • remove_if arbeitet nicht mit set iteratoren. Punkt.



  • khalderon schrieb:

    remove_if arbeitet nicht mit set iteratoren. Punkt.

    Richtig, weil remove_if die Reihenfolge in der Sequenz ändert. Da im set die Reihenfolge festgelegt ist, klappt das nicht.



  • ok, wieder was gelernt. Andere Frage: muss es überhaupt ein set sein?



  • Ja, weil set Duplikaten nicht erlaubt. Ich muss ständig Zeiger inserten. Im Fall wenn 2 oder mehrmals die gleiche Adresse inserted wird, passiert nix schlimmes (ein counter wird intern im set inkrementiert) und meine Anwendung funktioniert einfach problemlos.


Anmelden zum Antworten