Vektor: Iterator und eine Zählervariable gleichzeitig benutzen?



  • Hi, ich habe ein Problem beim löschen der Instanzen aus einem Vektor. Und zwar geht es darum, dass ich Abfrage, wenn eine Instanz außerhalb des Sichtfeldes ist, dass es es eine Variable bCleanUp auf TRUE stellt. Jedes mal, wenn jetzt neue Instanzen erstellt werden (ein Partikelsystem für Effekte), soll der Vektor, bevor er neue Instanzen erstellt, alle Instanzen mit dem bCleanUp = true aus dem Vektor entfernen. Das Problem ist, dass ich den Iterator und die Zählervariable nicht gleichzeitig verwenden kann:

    for(unsigned int i=0; i<ParticleVec.size(); i++)
    {
    	static CParticleVec::iterator iter = ParticleVec.begin();
    
    	if(ParticleVec.at(i)->bCleanUp == true)
    	{
    		delete (*iter);
    		ParticleVec.erase(ParticleVec.begin()+i);
    	}
    
    	iter++;
    }					
    
    for(int i=0; i<10; i++)
    	ParticleVec.push_back(new CParticle(pPlayer->GetX()+33, pPlayer->GetY()+8, 18*i, 1+i, makecol(255, 0, 0)));
    

    Jedoch jedes Mal, wenn ich diese Aktion eintreffen soll, sagt er mir im DebugModus: Assertion Failed! Expression: (this->_Has_Container()", 0)
    Line: 116

    Damit kann ich aber nicht so viel Anfangen. Wo ist da der Fehler? Danke schonmal, QuarZ



  • Bei diesem (für mich etwas übersichtlicheren Code) passiert leider genau das gleiche:

    for(CParticleVec::iterator iter = ParticleVec.begin(); iter<ParticleVec.end(); iter++)
    {
    	static int count=0;
    	if(ParticleVec.at(count)->bCleanUp == true)
    	{
    		delete *iter;
    		ParticleVec.erase(iter);
    	}
    	count++;
    }
    


  • 1. es wäre nicht schlecht zu wissen wo line 116 ist 🙂

    2. erase gibt einen iterator auf das nächste gültige element zurück

    iter = ParticleVec.erase(iter);
    


  • Hmm also Zeile 116 ist eine eine Variable in einer Klasse, die gar nicht zum Fehler passt oO
    Zu 2: Heißt das, dass ich jetzt einfach dieses erase rausnehmen soll?



  • http://www.c-plusplus.net/forum/viewtopic-var-t-is-177077-and-highlight-is-vorteile+dlls.html

    Dem Quellcode (und seinem "Stil") nach zu urteilen, ist das eher eine Assertion in dem entsprechendem Container (<vector>).

    Zu 2: Heißt das, dass ich jetzt einfach dieses erase rausnehmen soll?

    Das heisst, du sollst Helferleins Beitrag lesen und verstehen oder einfach seinen Quellcode so wie er ist in deinen uebernehmen...



  • struct CleanUp
    {
        bool operator()( CParticleVec::value_type p ) const
        {
            return p->bCleanUp? delete p, true: false;
        }
    };
    
        ParticleVec.erase( remove_if( ParticleVec.begin(), ParticleVec.end(), CleanUp() ),
            ParticleVec.end() );
    


  • outgelogged schrieb:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-177077-and-highlight-is-vorteile+dlls.html

    Dem Quellcode (und seinem "Stil") nach zu urteilen, ist das eher eine Assertion in dem entsprechendem Container (<vector>).

    Zu 2: Heißt das, dass ich jetzt einfach dieses erase rausnehmen soll?

    Das heisst, du sollst Helferleins Beitrag lesen und verstehen oder einfach seinen Quellcode so wie er ist in deinen uebernehmen...

    Ich möchte aber kein nächst gültiges Element haben sondern einfach nur ein Element aus dem Vektor löschen...Also nehm ich es einfach raus 😉



  • QuarZ schrieb:

    Ich möchte aber kein nächst gültiges Element haben sondern einfach nur ein Element aus dem Vektor löschen...Also nehm ich es einfach raus 😉

    doch - das willst Du schon - Du möchtest nämlich nach dem Löschen eines Elements mit dem nächsten weitermachen. Und wie soll den ein Iterator weiterzählen, wenn Du vorher das Element, auf welches der Iterator zeigt, gelöscht hast. Da hast Du den Ast abgesägt, auf dem Du gerade sitzt und anschließend willst Du weiter nach oben. Das geht einfach nicht.

    Die Methode erase liefert Dir nach dem Löschen des Elements den Iterator des folgenden, damit Du anschließend da weiter machen kannst. In diesem Fall darf der Iterator dann natürlich nicht mehr inkrementiert werden, denn das ist er ja quasi schon.

    Hier ist der Code der in Richtung Lösung zeigt:

    for(CParticleVec::iterator iter = ParticleVec.begin(); iter!=ParticleVec.end(); /*hier KEIN iter++*/ )
        {
            //static int count=0; // 'count' ist unnötig
    //        if(ParticleVec.at(count)->bCleanUp == true)
            if( (*iter)->bCleanUp )  // soll das aktuelle Element - also das auf das 'iter' zeigt - gelöscht werden?
            {
                delete *iter;
                iter = ParticleVec.erase(iter);  // erase liefert auch 'iter' auf das nächste Element
            }
            else
                ++iter; // nur wenn nicht gelöscht wird Iterator auf nächstes Element setzen
            //count++;
        }
    

    bleibt noch zu erwähnen, dass dieser Code noch suboptimal ist, da er sooft die Elemente im Vektor verschiebt (ich unterstelle es ist ein std::vector), wie es zu löschende Elemente gibt. Dafür gibt es aber die Algorithmen 'remove' und 'remove_if'. Schau Dir die mal an.

    Gruß
    Werner



  • Ach so gut danke! Jetz versteh ich das. Ich habe mir remove_if auch ma angeschaut und eine ähnliche lösung wie die von Take This geschrieben!

    mfg.


Anmelden zum Antworten