Problem mit Zeiger auf Listen-Element



  • Hallo, ich hab grad das Problem, dass ein Zeiger nach dem Verlassen der Methode BerechnePick immer NULL wird:

    inline BOOL CGame::BerechnePick(float *Distanz, CProduktionsGebeude* amNachsten, tbVector3 Punkt1, tbVector3 Punkt2, std::vector<CProduktionsGebeude>* Gebeude, std::vector<CProduktionsGebeude>::iterator dIter2)
    {
    	BOOL changed = FALSE;
    	tbVector3 Position;
    	float Distanz2;
    
    	for(std::vector<CProduktionsGebeude>::iterator dIter(Gebeude->begin()); dIter != Gebeude->end();++dIter)         
    	{
    		if(!dIter->m_bGerendert) continue;
    		if(tbLineHitsModel(Punkt1, Punkt2, dIter->m_sTyp->Modeldatei, dIter->m_mTranslation, dIter->m_mInvTranslation, 10.0f, &Position))
    		{
    			Distanz2 = tbVector3LengthSq(Position-g_vCameraPos);
    			if(*Distanz == -1.0f || Distanz2 < *Distanz)
    			{
    				*Distanz = Distanz2;
    				amNachsten = &(*dIter);
    				if(dIter2 != NULL) dIter2 = dIter;
    				changed = TRUE;
    			}//End of if
    		}//end of if
    	}//End of for
    	return changed;
    }
    inline BOOL CGame::GebeudePicked(BOOL loeschen, BOOL wirklich_loeschen, tbVector3 Punkt1, tbVector3 Punkt2)
    {
    	tbVector3 Position;
    	float Distanz = -1.0f;
    	float Distanz2;
    	CProduktionsGebeude* amNachsten = NULL;
    	CArbeiterGebeude* amNachsten2 = NULL;
    
    if(!wirklich_loeschen)
    {	
    	BerechnePick(&Distanz, amNachsten, Punkt1, Punkt2, &Kohlebergwerke);
    	BerechnePick(&Distanz, amNachsten, Punkt1, Punkt2, &Raffenerien);
    	BerechnePick(&Distanz, amNachsten, Punkt1, Punkt2, &Backereien);
    }
    else
    {
    	std::vector<CProduktionsGebeude>::iterator Zeiger_auf_Liste;
    	std::vector<CArbeiterGebeude>::iterator Zeiger_auf_Liste2;
    	std::vector<CProduktionsGebeude>* Gebeudeliste;
    	if(BerechnePick(&Distanz, amNachsten, Punkt1, Punkt2, &Kohlebergwerke, Zeiger_auf_Liste)) Gebeudeliste = &Kohlebergwerke;
    	if(BerechnePick(&Distanz, amNachsten, Punkt1, Punkt2, &Raffenerien, Zeiger_auf_Liste)) Gebeudeliste = &Raffenerien;
    	if(BerechnePick(&Distanz, amNachsten, Punkt1, Punkt2, &Backereien, Zeiger_auf_Liste)) Gebeudeliste = &Backereien;
    }
    

    Wenn GebeudePicked im ersten if-Zweig BerechnePick aufruft, trifft in dieser die tbLineHitsModel-Methode zu, so dass die Distanz und ein Zeiger auf ein Element des vectors gespeichert werden sollen (amNachsten und Distanz).
    Wenn er jetzt aber die Methode verlässt beleibt Distanz wie erwartet erhalten, aber der Zeiger auf die Klasse im Vector ist wieder Null.
    Wenn das ein flüchtiges Element dieser Methode wäre, kann ich das ja noch verstehen, da die lokalen Daten nach dem Methodenaufruf ja gelöscht werden, aber eigentlich sollte das ein Zeiger auf eine Membervariable der Vector-Liste sein, oder hab ich das falsch realisiert?

    Wenn ich schon dabei bin, noch eine Frage:
    Im else-Zweig der GebeudePicked-Methode wird noch der Iterator der Liste benötigt, an dem tbLineHitsModel zutraf. Mein Visual C++ 6.0 gibt die Warnung aus, dass Zeiger_auf_Liste und Zeiger_auf_Liste2 nicht initialisiert worden wären, bevor sie genutzt werden. Ist das wirklich falsch realisiert, oder brauch ich die Warnung nicht beachten?

    Vielen Dank für eine Antwort

    Andreas



  • Du übergibst den Pointer 'amNachsten' "per value". Das bedeutet, dass jede Änderung in der Funktion außerhalb keinen Effekt hat, da bei der Übergabe "per value" eine Kopie auf dem Programmstack angelegt wird. Der Ausdruck

    amNachsten = &(*dIter);
    

    ändert nur die Kopie.

    Du kannst eine Referenz auf den Pointer übergeben - etwa so:

    inline BOOL CGame::BerechnePick(float *Distanz, CProduktionsGebeude*& amNachsten, tbVector3 Punkt1, tbVector3 Punkt2, std::vector<CProduktionsGebeude>* Gebeude, std::vector<CProduktionsGebeude>::iterator dIter2)
    {
    

    .. das sollte schon reichen.

    Gruß
    Werner



  • Und zu deiner 2. Frage:
    Ja, die Warnung ist korrekt!

    Du übergibst auch den Iterator nur als Kopie (Call by Value).
    Und in der Methode macht die Überprüfung "if(dIter2 != NULL)" überhaupt keinen Sinn. Ein Iterator entspricht nicht einer Übergabe als Zeiger!!!

    Und du solltest deinen Code auf einen einheitlichen Stil bringen, d.h. der Mix aus Zeigern und Iteratoren ist sehr unübersichtlich (und fehlerhaft).
    Benutze am besten nur Referenzen und Iteratoren.

    Desweiteren könntest du für deine ganzen Gebäudetypen Arrays (bzw. std::vector<>) verwenden und diese dann in einer Schleife abarbeiten (anstatt einzeln aufzurufen).



  • Hallo, erstmal vielen Dank für die Antworten!!!!

    Desweiteren könntest du für deine ganzen Gebäudetypen Arrays (bzw. std::vector<>) verwenden und diese dann in einer Schleife abarbeiten (anstatt einzeln aufzurufen).

    Sry, das hab ich leider nicht verstanden, wie meinst das, die verschiedenen Gebäudetypen (Kohlebergwerk, etc.) sind doch jeweils in einem Vector zusammengefasst. (sry wenn das am Titel des Eintrags "Listen-Element" liegt, für mich ist ein vector auch so eine Art liste^^)
    Ich brauche im else Zweig allerdings noch den Iterator, bei dem sich das Element befindet, das angeklickt (picked) wurde um es später mit erase() aus dem Vector zu entfernen.
    Wie kann man dass denn realisieren, dass die Methode BerechnePick den Iterator zurückliefert, (aber nur wenn er benötigt wird und zwar im else-zweig) wenn ein Vergleich mit NULL unzulässig ist. In der Headerdatei steht:

    BOOL BerechnePick(float *Distanz, CProduktionsGebeude* amNachsten, tbVector3 Punkt1, tbVector3 Punkt2, std::vector<CProduktionsGebeude>* Gebeude, std::vector<CProduktionsGebeude>::iterator dIter2 = NULL)
    

    welches er ohne meckern übersetzt hat.

    Viele Grüße
    Andreas


Log in to reply