Mehrere Element in std::vector löschen



  • Warum gehst du nicht einfach rückwärts durch dein set?



  • Damit Jesters Vorschlag nicht untergeht:

    #include <algorithm>
    
    struct MyPred
    {
        bool operator() (const ShipVectorContent& elem)
        {
            // wenn elem deleted werden soll -> return true
            return false;
        }
    };
    
    vector<ShipVectorContent>::iterator new_end = std::remove(ShipVector.begin(), ShipVector.end(), MyPred());
    
    ShipVector.erase(new_end, ShipVector.end());
    

    MfG SideWinder



  • std::erase( std::remove( ShipVectr.begin(), ShipVector.end(), MyPred() );
    

    so! 🙂

    Edit: Ups, zu spät...



  • Dass ich die Indexe abspeichere hat schon einen Grund:

    Das Problem ist folgendes:
    Das ganze ist ein Kampfsimulator, der einen Kampf zwischen zwei Raumschiffflotten berechnen soll.
    Wird ein Schiff zerstört habe ich es (wie ihr vorgeschlagen habt) in meiner ersten Version gleich gelöscht.
    Das Problem das ich dabei hatte war folgendes: Jedes Schiff hat eine bestimmte Wahrscheinlichkeit getroffen zu werden, abhängig von seiner Größe.
    Entferne ich das Schiff sofort, muss ich jedesmal wenn ein Schiff zerstört wird die Trefferwahrscheinlichkeit aller Schiffe neu berechnen.
    Meine Idee war also, die zerstörten Schiffe bis zum Ende einer Runde noch da zu lassen. (Dann können sie zwar immer noch getroffen werden, etwas unrealistisch, aber wenn ich genügend Geschwindigkeit dabei raushole geht das in Ordnung).
    Wird ein Schiff zerstört, speichere ich also seinen Index ab (dann weiß ich ja, welches Schiff kaputt ist, und muss nicht wieder den ganzen Array nach kaputten Schiffen durchsuchen).

    Und am Ende der Runde lösche ich die kaputten Schiffe aus der Flotte Das ist das was mein Code oben machen sollte).
    Dabei muss ich dann die Trefferwahrscheinlichkeit nur EINMAL berechnen

    Aber ich werd jetzt mal die Schiffe von hinten löschen, das sollte gehen.



  • Ok, ich hab jetzt euren Vorschlag umgesetzt und die Schiff von hinten her gelöscht.
    Ergebnis: gleiches Problem wie vorher :(.

    Code:

    INDEX_SET::reverse_iterator index_reviter;
    	index_reviter=ship_indexes.rbegin();
    
    	while(index_reviter!=ship_indexes.rend())//clear all ships at the indexes in ShipVector
    	{
    		if(count_deletes>0)
    			_DPRINTL("count_deletes>0");
    		//save the size of the ship
    		shipsize_buffer_vector.push_back(ShipVector.at(*index_reviter)->GetSize());
    		//clear ship from ShipVector
    		_DPRINTL("delete ship [%p]: *index_reviter: %d",ShipVector.at(*index_reviter),*index_reviter);
    		delete ShipVector.at(*index_reviter); //delete the Ship, because it was created with new
    		_DPRINTL("deleted ship [%p]!",ShipVector.at(*index_reviter));
    		ShipVector.erase(ShipVector.begin() + *index_reviter); //don't remove the brackets, or the iterator will jump for one moment over his bounds, that leads in VS to an assertion failed!
    
    		count_deletes++;
    
    		_DPRINTL("DUMP: ShipVector after %d. delete",count_deletes);
    		DumpShipVector();
    		_DPRINTL("END DUMP: ShipVector after %d. delete",count_deletes);
    
    		index_reviter++;
    	}
    

    Mir ist allerdings was aufgefallen:
    Schaut euch dieses Bild hier an: http://666kb.com/i/anhp4ws10z83hogy2.png

    Seht ihr auf was index_reviter zeigt?
    Genau auf eine negative Zahl. Das kann doch nicht sein?????
    Ich meine ich weiß ja nicht, es ist ja alles richtig programmiert soweit ich das sehe.
    Und was am aller seltsamsten ist:
    Gehe ich weiter, und schaue was ShipVector.at(size_t pos) macht, dann ist pos nicht der (falsche negative) Wert von index_reviter, sondern der richtige, auf den index_reviter auch zeigen sollte 😮 .
    Was soll das? Ein Bug in Visual Studio oder ein Fehler von mir???
    Bugs äußern sich ja manchmal in der schrägsten Dingen 😃
    Langsam hab ich das Gefühl, das mein Fehler irgendwo anderst liegt 😞
    Aber wo, das hier ist die einzige Stelle an der ich delete benütze...



  • Frage fürs eigene Verständnis: wieso dererenzierst du den iterator beim delete (also beim aufruf von at, genauer gesagt)



  • Also, ship_indexes speichert die Indexe der Elemente ab, die aus ShipVector gelöscht werden sollen.
    index_reviter ist ein Iterator, der auf ein Element in ship_indexes zeigt
    ShipVector enthält die Zeiger auf alle Schiffe in der Flotte.
    Da ich alle Schiffe mit new erstellt habe, muss ich sie, wenn ich sie aus der Flotte mit erase lösche, mit delete wieder löschen. (Sonst werden sie ja nie gelöscht -> Memory Leak)

    Deswegen mach ich

    delete ShipVector.at(*index_reviter); //delete the Ship, because it was created with new
    

    Heißt nix anderes als "Lösche jetzt das Schiff, das zerstört worden ist"
    Und *index_reviter sollte ja der Index des Schiffes sein das gelöscht wird

    Das war doch deine Frage oder?? 😃



  • Hmm, wenn man einen index dereferenziert erhält man das Element auf das er zeigt soweit ich bisher dachte.

    quasi:

    std::vector<int> v;
    v.push_back(5);
    std::iterator it=v.begin();
    assert((*it)=5);
    

    Von daher würde ich einfach

    delete *it;
    

    schreiben.



  • naja, aber da verwechselst du was:

    index_iter zeigt auf ship_indexes, der die Indexe der Schiffe enthält die gelöscht werden sollen.
    ShipVector enthält dann die Zeiger auf die Schiffe.

    Deswegen

    delete ShipVector.at(*index_reviter); //delete the Ship, because it was created with new
    


  • Achsoooo, *Klick*
    Sorry, hatte glatt vergessen, dass das ja nicht der vector ist auf den der iterator zeigt.

    Entschuldige dann.


Anmelden zum Antworten