Objekt aus einem vector entfernen!



  • 1. der Iterator soll ein CString sein (igit, nimm std::string für BEIDE!)

    ...aber, wie kann ich dann ein bestimmtes Element aus einem Vektor löschen, wenn die erase Methode ein iterator verlangt und wenn der iterator ein CString ist, dann kann ich ihn nicht inkrementieren, wie man das aus dem "schönen" MSDN-Beispiel kennt...

    using namespace std;   
       vector <int> v1;
       vector <int>::iterator Iter;
    
       v1.push_back( 10 );
       v1.push_back( 20 );
       v1.push_back( 30 );
       v1.push_back( 40 );
       v1.push_back( 50 );
    
       cout << "v1 =" ;
       for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
          cout << " " << *Iter;
       cout << endl;
    

    2. der Code den Du gepostet hast ist schwachsinn.

    ja, gut, ich sehe es ja ein, 🙄 dass dieser Quellcode auf ersten Blick oder in dieser Aufstellung auf das Problem bezogen schwachsinnig erscheint, aber diese Schleife ist ja noch zu anderen Zwecken da, die ich jetzt nicht aufgeführt habe...

    was würdest Du mir empfehlen, wie ich ein bestimmtes Objekt aus einem vektor löschen kann?

    Gruss,

    chullain



  • Der Code ist schon konfus, da wir nicht wissen welchen Typ user, v1 und userArrayOld sind. Ist alles ein wenig durcheinandergewürfelt. Die Grundsätzliche strategie wäre jedoch:

    for(std::vector< std::string >::iterator iter = array.begin(); iter != array.end(); ++iter)
    	if (*iter == vergleichsstring) iter = array.erase(iter);
    

    Wichtig ist, dass du iter nach dem erase neu setzt, da durch das erase die iteratoren ungültig werden. Wenn du einfach alle Elemente mit einem bestimmten Wert löschen willst ist der folgende Weg einfacher:

    array.erase(remove(array.begin(), array.end(), vergleichsstring), array.end())
    


  • Ein RIESEN Dankeschön an Euch alle, hat prima funktioniert...

    ..nur eins würde ich gerne zur Verständlichkeit wissen, also dieser Iterator hat auch selbst eine Tabelle mit einem Index, sonst könnte ich ihn doch nicht inkrementieren, oder?wenn er von Typ String ist...

    gruss,

    chullain



  • der iterator von std::vector ist ein einfacher zeiger vom typ, den du dem vector übergeben hast, also in deinem fall
    Cstring*



  • otze schrieb:

    der iterator von std::vector ist ein einfacher zeiger vom typ, den du dem vector übergeben hast, also in deinem fall
    Cstring*

    Darauf kann uns sollte man sich nicht verlassen. In der aktuellen Version eines Compilers mag das gelten, aber bei anderen Compilern oder in einer neueren Version des gleichen Compilers kann sich das schnell ändern.



  • 1. ich kenn keinen compiler der den vector mit ner eignen iterator klasse implementiert,wenns wieder erwarten anders ist, dann is die version mieserabel(und wieso? ein iterator muss sich wie ein zeiger verhalten,dazu kommt noch, dass der vector den speicher am stück hält, und somit der standardzeiger einfach nur ideal ist,es gibt nichts schnelleres).
    ansonsten is man mit vector<Type>::iterator immer auf der sicheren seite.



  • otze schrieb:

    1. ich kenn keinen compiler der den vector mit ner eignen iterator klasse implementiert,wenns wieder erwarten anders ist, dann is die version mieserabel(und wieso? ein iterator muss sich wie ein zeiger verhalten,dazu kommt noch, dass der vector den speicher am stück hält, und somit der standardzeiger einfach nur ideal ist,es gibt nichts schnelleres).
    ansonsten is man mit vector<Type>::iterator immer auf der sicheren seite.

    Die libstdc++ hat eigene Iteratorklassen. Diese haben auch dies selbe Performance wie Pointer, verhindern aber, dass der Programmierer ungültigen Code schreibt.



  • wenn sie es verhindern, dann is da irgendwo ne if abfrage drin->langsamer.



  • otze schrieb:

    wenn sie es verhindern, dann is da irgendwo ne if abfrage drin->langsamer.

    Nix Abfrage, das macht der Compiler beim kompilieren.



  • das hört sich für mich nah nem echt guten iterator an, aber sag an, wie macht er denn das?

    vector<int> a;
    for(vector<int>::iterator b=a.begin();b<=a.end();++b){
        //do something
    }
    


  • vector<int> a;
    for(vector<int>::iterator b=a.begin();b<=a.end();++b){
        //do something
    }
    

    darauf würde ich mich nicht unbedingt verlassen. ++b besagt nur, dass ich zum nächsten element des vectors gehe. bei einem anderen container können die elemente anders angeordnet sein und womöglich würde die bedingung erfüllt, ohne das alle elemente durchgegangen sind. a.end beschreibt nur das end-element des vectors. wie der zugriff intern geschieht ist erstmal für mich als nutzer nicht relevant. besser wäre es folgendes zu nehmen, damit ist man auf der sicheren seite.

    vector<int> a;
    for(vector<int>::iterator b = a.begin(); b != a.end(); ++b){
        //do something
    }
    

    nochwas, normalerweise ist der vector nicht unbedingt die erste wahl, wenn man elemente häufiger entfernt, da der komplette inhalt des vectors womöglich neu angelegt wird.

    gruss,
    Sebastian



  • es geht hier speziell um std:.vector,hier das passende zitat:

    der iterator von std::vector ist ein einfacher zeiger vom typ, den du dem vector übergeben hast, also in deinem fall Cstring*

    Es geht definitiv nicht um list/map oder andre sachen, ich hab mich ganz klar auf den vector beschränkt, und da is festgelegt, dass ein ++iterator zum nächsten im speicher liegenden element führen muss(und es wurde hier in dem thread noch in keinem beitrag ein anderer container ausser vector genannt)

    desweiteren beschreibt end nicht das end element des vectors, sondern das past-the-end element, was ein großer unterschied ist; das end element ist gültig, das past the end nicht.
    btw: der iterator von vector ist ein random access iterator, ein </<=/>/>= muss gültig sein, und zwar immer. ein for(;a<b;++a) ist äquivalent zu for(;a!=b;++a),unter der voraussetzung, das a nicht größer als b ist, indem fall hat man aber bei a!=b ne endlosschleife-sehr interessant.

    was lernt man daraus a) alle beiträge lesen
    b) etwas von den internen zusammenhängen wissen



  • otze schrieb:

    das hört sich für mich nah nem echt guten iterator an, aber sag an, wie macht er denn das?

    vector<int> a;
    for(vector<int>::iterator b=a.begin();b<=a.end();++b){
        //do something
    }
    

    Was soll er da besonders machen? Außer, dass b<=a.end() gefährlich ist.



  • nich nur gefährlich, sondern der punkt, wo dein iterator sagen MUSS, dass das nich geht, ansonsten is nämlich jeder übertritt möglich, und nix mit fehler erkennung zur compilezeit.



  • otze schrieb:

    nich nur gefährlich, sondern der punkt, wo dein iterator sagen MUSS, dass das nich geht, ansonsten is nämlich jeder übertritt möglich, und nix mit fehler erkennung zur compilezeit.

    Ich schrieb nicht, dass dieser alle Fehler findet. Er erlaubt die geleichen Fehler wie ein Pointer bis auf alle Fehler, die aus der Annahme resultieren, der Iterator müsse ein Pointer sein.

    #include <vector>
    
    int main() {
    	std::vector<int> vec(5);
    	int * p = vec.begin();  // Fehler
    	int * p2 = &*(vec.begin()); // OK
    }
    


  • Hier ist ein Usenet Artikel, der Gründe dafür angibt, warum immer mehr STL Implementierungen darauf verzichten, den vector Iterator als Pointer zu implementieren:

    http://groups.google.de/groups?selm=240720020933594031%25hinnant%40metrowerks.com



  • Ich schrieb nicht, dass dieser alle Fehler findet. Er erlaubt die geleichen Fehler wie ein Pointer bis auf alle Fehler, die aus der Annahme resultieren, der Iterator müsse ein Pointer sein.

    "das beste feature unseres autos ist, dass es sofort explodiert, wenn es als Vase verwendet wird" :p



  • was lernt man daraus a) alle beiträge lesen
    b) etwas von den internen zusammenhängen wissen

    ich benutze vector und andere stl container seit geraumer zeit und weiss um die zusammenhänge einigermassen bescheid. ich habe nicht ohne grund darauf hingewiesen, dass es sich nicht gerade anbietet bei einem vector elemente zu entfernen.

    der iterator von std::vector ist ein einfacher zeiger vom typ, den du dem vector übergeben hast, also in deinem fall
    Cstring*

    wie Ponto schon geschrieben hat, sollte man sich darauf nicht verlassen, der Iterator selbst fungiert hier als Interface. wie du selbst sagst, muss ein iterator sich nur wie ein pointer verhalten, demnach entsprechende operatoren zur verfügung stellen.

    nich nur gefährlich, sondern der punkt, wo dein iterator sagen MUSS, dass das nich geht, ansonsten is nämlich jeder übertritt möglich, und nix mit fehler erkennung zur compilezeit.

    der Iterator kann dies nicht sagen, da er nix von dem Vergleich <= weiss. dafür ist der Iterator typensicher und der compiler gibt fehlermeldungen aus. dies ist mir bei pointern nicht unbedingt gegeben.

    gruss,
    Sebastian


Anmelden zum Antworten