Problem mit List, Iterator und Pointern auf Objekte



  • Was soll denn jetzt die for Schleife in der while Schleife?



  • Also ich hätte noch einen weiteren allgemeinen Tipp zu deinem ersten Beispiel (ist das jetzt gelöst? Der neue Code sieht ja doch ganz anders aus!). Und zwar würde ich da noch empfehlen, dieses Riesen-if hier (if( m_ItShot->OL().x <= 0 || m_ItShot->OL().x >= SCREEN_WIDTH || m_ItShot->OL().y <= -100 || m_ItShot->OL().y >= SCREEN_HEIGHT ) {) in eine Funktion zu schreiben. Zum Beispiel bool hasLeftScreen(const Sprite &) (oder auch andersrum: isOnScreen, je dachdem, was besser passt). Dann kann man sowas wie myList.erase(remove_if(begin(myList), end(myList), hasLeftScreen), end(myList)) schreiben und sofort ist der Befehl klar (und vor allem richtig, ohne dass du über einen Index oder sowas nachdenken musst).

    Was willst du jetzt in deinem neuen Quelltext tun - jeden Shot mit jedem Ballon vergleichen? Jedes mit jedem klingt immer irgendwie gefährlich langsam, vor allem wenn du dann noch Listen hast (hast du eigentlich einen guten Grund für std::list? Aber andere Baustelle...). Wenn beides wenige Elemente enthält, dann vergleiche meietwegen auch alles mit allem. Aber dann wäre es vielleicht hilfreich, die innere Schleife in eine Funktion zu tun und zu benennen.



  • Was willst du jetzt in deinem neuen Quelltext tun - jeden Shot mit jedem Ballon vergleichen? Jedes mit jedem klingt immer irgendwie gefährlich langsam

    Ja das stimmt. Ich muss alles nochmal neu überdenken. Danke für die Hilfe. Ich melde mich mal falls ich weiter gekommen bin.



  • Ich habe jetzt wirklich viel herumprobiert und komme zu dem Ergebnis das die folgende Methode
    Pointer von Objekten in einer Liste zu hinterlegen als einzige in meinem Projekt zu gerenderten Ergebnissen
    führt. Ich muss wohl eher einen Fehler gemacht haben als ich die vielen verschachtelten Schleifen erstellt habe.
    Wenn ich die Kollisionsschleifen in meiner Gameschleife auskommentiere bekomme ich auch keine Fehlermeldung.

    list<CObjekt> ObjektListe;
    list<CObjekt>::iterator ObjektIterator;
    
    while( TimerA >= TimerB) {
       CObjekt *pPointerX = new CObjekt( BspWertA, BspWertB );
       pPointerX->Memberfunktion("BspDateiname.png");
       ObjektListe.push_back(*pPointerX);
       TimerA = 0;
    }
    
    for(ObjektIterator = ObjektListe.begin(); ObjektIterator != ObjektListe.end(); ++ObjektIterator) {
       ObjektIterator->Update();
       ObjektIterator->Render();
    }
    
    ObjektListe.clear();
    


  • Warum "new"? Du hast da einen schönen Memory Leak produziert.



  • Wie teste ich mein Programm effektiv auf Memory Leaks ? Etwa mit VS 2019 Community ?

    Link Text



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

    Pointer von Objekten in einer Liste zu hinterlegen

    Du hinterlegst keine Pointer!



  • Habe folgende Anleitung gefunden:
    Memory Leaks finden

    Und Ja es gibt welche:
    Screenshot



  • @_andi84 Für Linux gibt es Valgrind, was da recht mächtig ist. Für Windows gibt es auch tools, die nach Speicher Problemen suchen können, siehe vlt: https://stackoverflow.com/questions/413477/is-there-a-good-valgrind-substitute-for-windows

    Regel Nummer 1 um Memory Leaks zu verhindern: Keine manuelle Speicherverwaltung (kein new)!



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

    Wie teste ich mein Programm effektiv auf Memory Leaks ?

    Das Memory Leak ist in der while Schleife. Da braucht man nichts zu suchen!



  • Wie kann ich denn auf die Objekte zugreifen wenn ich die ohne new direkt als ganzes Objekt in der Liste hinterlege ?
    Weil Iterator->Methode() funktioniert irgendwie nicht.



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

    funktioniert irgendwie nicht

    ist keine Fehlerbeschreibung



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

    while( TimerA >= TimerB) {
    CObjekt *pPointerX = new CObjekt( BspWertA, BspWertB );
    pPointerX->Memberfunktion("BspDateiname.png");
    ObjektListe.push_back(*pPointerX);
    TimerA = 0;
    }

    Was spricht denn gegen:

    while( TimerA >= TimerB) {
       auto object = CObjekt( BspWertA, BspWertB );
       object.Memberfunktion("BspDateiname.png");
       ObjektListe.emplace_back(object);
       TimerA = 0;
    }
    

    Das hat nichts mit Iteratoren zu tun. Iteratoren sind, wie der Name sagt, zum iterieren durch Container und sind irgendwie eine Referenz auf die entsprechende Position im Container, d.h. du kannst über den Iterator auf deine Objekte zugreifen.



  • ...und wenn dein CObjekt Probleme beim Kopieren macht, dann machst du statt deiner std::list<CObject> eben eine std::list<std::unique_ptr<CObject>>. Dann kannst du sowas machen und brauchst kein delete:

    auto pPointerX = std::make_unique<CObjekt>( BspWertA, BspWertB );
    pPointerX->Memberfunktion("BspDateiname.png");
    ObjektListe.push_back(std::move(pPointerX));
    

    (und warum eigentlich std::list statt std::vector - sicher dass du eine Liste brauchst?)



  • @wob
    wenn ich mir die Kopie sparen wollen würde, würde ich wohl sowas machen:

    while( TimerA >= TimerB) {
       ObjektListe.emplace_back(BspWertA, BspWertB );
       ObjektListe.back().Memberfunktion("BspDateiname.png");
       TimerA = 0;
    }
    

    Aber ich glaube, dass, wenn CObjekt nicht Kopierbar ist bzw da Probleme macht, _andi84 noch ganz andere Probleme bekommt.

    Und, weil ich es auch nicht verstehe: Warum list und nicht vector?



  • Ich habe es jetzt hinbekommen:

    So erzeuge ich die Objekte (heißen inzwischen CParticle 😉 ):

                           if (Zeitgeber.GetTimerTicks() >= SpawnTime) {
    
    				SDL_Point StartPos = { 400,300 };
    
    				srand(SDL_GetTicks());
    
    				float fAngle = (float)(rand() % 360);
    
    				SDL_Log("%f", fAngle);
    
    				CParticle* pParticle = new CParticle(StartPos, 0.5, fAngle);
    
    				ParticlesList.push_back(pParticle);
    
    				SpawnTime = Zeitgeber.GetTimerTicks() + 1;
    			}
    

    So werden diese aufgerufen:

                           for (myParticle = ParticlesList.begin(); myParticle != ParticlesList.end(); ++myParticle) {
    				(*myParticle)->Update();
    				(*myParticle)->Render();
    			}
    

    Und so lösche ich diese wieder:

            for (myParticle = ParticlesList.begin(); myParticle != ParticlesList.end();) {
    		delete(*myParticle);
    		myParticle = ParticlesList.erase(myParticle);
    	}
    

    Hoffe es hilft vielleicht irgendwem weiter. Gruß _andi84



  • Warum new und delete? Das ist nicht nötig und sollte vermieden werden.



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

    srand(SDL_GetTicks());

    Nein! Einmal!



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

            for (myParticle = ParticlesList.begin(); myParticle != ParticlesList.end(); ++myParticle) {
      		(*myParticle)->Update();
      		(*myParticle)->Render();
      	}
    

    Das kannst du einfacher schreiben:

    for (auto *particle : ParticlesList) {
        particle->Update();
        particle->Render();
    }
    

    ParticlesList hört sich wie eine Klasse an. Ich würde Variablen immer mit Kleinbuchstaben beginnen. Und ist das "List" im Namen notwendig? Schlage Umbenennung in particles vor.



  • @_andi84 sagte in Problem mit List, Iterator und Pointern auf Objekte:

    float fAngle = (float)(rand() % 360);

    Was tut der Cast hier deiner Meinung nach?


Log in to reply