Problem mit List, Iterator und Pointern auf Objekte



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

    Nicht-Erase-Fall

    Also in etwa so ?

    m_ItShot = m_ShotList.begin();
    
    	while (m_ItShot != m_ShotList.end()) {
    		if (m_ItShot->OL().x <= 0 || m_ItShot->OL().x >= SCREEN_WIDTH
    			|| m_ItShot->OL().y <= -100 || m_ItShot->OL().y >= SCREEN_HEIGHT) {
    			m_ItShot = m_ShotList.erase(m_ItShot);
    			++m_ItShot;
    		}
    	}
    


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

    Also in etwa so ?

    Nein. Ist es zu viel verlangt, wenn du dir das oben verlinkte Beispiel der Doku anguckst?



  •         // Kollision zwischen Schussliste und Fensterrahmen:
    	for(auto m_ItShot = m_ShotList.begin(); m_ItShot != m_ShotList.end();) {
    		if( m_ItShot->OL().x <= 0 || m_ItShot->OL().x >= SCREEN_WIDTH 
    		|| m_ItShot->OL().y <= -100 || m_ItShot->OL().y >= SCREEN_HEIGHT ) {
    			m_ItShot = m_ShotList.erase(m_ItShot);
    		}
    		else {
    		        ++m_ItShot;
    		}
    	}
    

    Ich glaube ich habe Schwierigkeiten zu verstehen ob der Iterator eine Position oder ein Pointer auf ein Objekt ist.
    Bei meinem Beispiel hier wird dann also der Iterator im Löschfall auf das Ende gesetzt ? Also wäre m_ItShot = m_ShotList.erase(m_ItShot); genau so wie m_ItShot = m_ShotList.end(); ?



  • OT:

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

    m_ShotList.push_back(*pShot);

    Dir ist schon klar, dass du hier eine Kopie in die Liste steckst und den Speicher nicht freigibst? Warum new?



  • Mit m_ShotList.clear() kann ich doch alles wieder freigeben ?
    Das ist ja auch ein unvollständiges Codebeispiel.



  • Da:

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

    m_ShotList.push_back(*pShot);
    

    wird das Objekt auf das pShot zeigt kopiert. Das "Original", das worauf pShot zeigt wird nie freigegeben. Warum new?



  • zu müde. heute wird das nichts mehr. 😴 🙂



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

    Ich glaube ich habe Schwierigkeiten zu verstehen ob der Iterator eine Position oder ein Pointer auf ein Objekt ist.

    Man kann einen Iterator als Verallgemeinerung solcher Konzepte wie "Pointer" oder "Position" betrachten. "Position" passt eigentlich ganz gut, allerdings nicht im konkreten Sinne z.B. eines Array-Index, sondern eher als abstrakte Position.

    Bei meinem Beispiel hier wird dann also der Iterator im Löschfall auf das Ende gesetzt ? Also wäre m_ItShot = m_ShotList.erase(m_ItShot); genau so wie m_ItShot = m_ShotList.end(); ?

    Nein. erase() gibt einen Iterator auf das nachfolgende Element zurück. Nur wenn es kein solches gibt, weil du das letzte Element gelöscht hast, wird der end()-Iterator zurückgegeben.

    Ansonsten: Ausschlafen und nochmal in Ruhe ansehen. Vor allem die Anmerkungen zu dem unnötigen und fehlerhaft verwendeten new.



  • 
    // Dieses habe ich als Membervariablen der Klasse CGame festgelegt:
    	list<CSprite> m_ShotList;
    	list<CSprite>::iterator m_ItShot;
    
    // Dies rufe ich in der Spawn Funktion auf:
    	if(m_bFire && m_pShotTimer->Timeout()) {
    	CSprite pShot(180,8.0f);
    	pShot.Load("img/schiff/shotimage2.png");
    	pShot.SetPos(m_pRaumschiffLinksRechts->GetPos().x + 160,m_pRaumschiffLinksRechts->GetPos().y + 120);
     	m_ShotList.push_back(pShot);		
    	}
    

    So sieht das jetzt mit dem erase aus:

    while(m_ItShot != m_ShotList.end()) {
    
    for(m_ItBallon = m_BallonList.begin(); m_ItBallon != m_BallonList.end(); ++m_ItBallon) {
    						
    	if(Entfernung(m_ItShot->GetPos().x,m_ItShot->GetPos().y,m_ItBallon->GetPos().x,m_ItBallon->GetPos().y) <= 30.0f) {
    		m_ItShot = m_ShotList.erase(m_ItShot);
    		m_nPunktestand += 30;
    	} else {
    		++m_ItShot;
    	}
    }}
    

    Leider wird nichts mehr gerendert.

    // So iteriere ich durch die Liste:
    	m_ItShot = m_ShotList.begin();
    	while( m_ItShot != m_ShotList.end()) {
    		m_ItShot->Render(0);
    		++m_ItShot;
    	}
    

    Ich weiß nicht mehr weiter 😭



  • 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.


Log in to reply