Probleme mit std::list...::iterator



  • Hallo zusammen ich habe ein kleines Problem mit dem, bei mir eingesetzten Befehl

    std::list<Tree<T>*>::iterator
    

    hier der Quellcode:

    main2.cpp

    #include <stdlib.h>
    #include "main2.h"
    
    template<class T>
    Tree<T>::Tree(T* element) : element(&element)
    {
            leaf = true;
    }
    
    template<class T>
    Tree<T>::~Tree()
    {
            if(!leaf)
            {
                    for (std::list<Tree<T>*>::iterator it = child.begin(); it != child.end(); it++)
                    {
                            *it.~Tree();
                    }
            }
            for (std::list<Tree<T>*>::iterator it = parent.begin(); it != parent.end(); it++)
                    {
                    *it.deletechild(this)
                    }
            delete this;
    }
    
    template<class T>
    T* Tree<T>::getelement()
    {
            return *this.element;
    }
    
    template<class T>
    bool Tree<T>::deletechild(Tree<T>* tokill)
    {
            for (std::list<Tree<T>*>::iterator it = child.begin(); it != child.end(); it++)
            {
                    if( tokill == it){
                            child.erase(it);
                            return true;
                    }
            }
            // Error code hier einfügen
            return false;
    }
    
    template<class T>
    bool Tree<T>::makeparent (Tree<T>* newParent){
            if (*newParent.makechild(this)){
                    parent.push_back(newParent);
                    return true;
            }
            else{
                    //Error code hier einfügen
                    return false;
            }
    }
    
    template <class T>
    void Tree<T>::makenewchild(){
            child.push_back(new Tree<T>);
    }
    
    template<class T>
    bool Tree<T>::makechild(Tree<T>* inTree)
    {
            child.push_back(inTree);
            return true;
    }
    

    und dann noch die main2.h

    #include <iostream>
    #include <list>
    
    /**
     * 
     */
    template<class T>
    class Tree
    {
    private:
            T* element;
    public:
            std::list<Tree<T>*> child;
            std::list<Tree<T>*> parent;
            Tree(T*);
            ~Tree();
            bool makechild(Tree<T>*);
            bool deletechild(Tree<T>*);
            bool makeparent(Tree<T>*);
            void makenewchild();
            T* getelement();
            bool leaf;
    };
    

    ich bekomme da immer eine Reihe an Fehlern raus... (für jede "for" schleife)

    /home/evd/main2.cc: In destructor ‘Tree<T>::~Tree()’:
    /home/evd/main2.cc:15:8: error: need ‘typename’ before ‘std::__cxx11::list<Tree<T>*>::iterator’ because ‘std::__cxx11::list<Tree<T>*>’ is a dependent scope
       for (std::list<Tree<T>*>::iterator it = child.begin(); it != child.end(); it++)
            ^~~
    /home/evd/main2.cc:15:38: error: expected ‘;’ before ‘it’
       for (std::list<Tree<T>*>::iterator it = child.begin(); it != child.end(); it++)
                                          ^~
    /home/evd/main2.cc:15:58: error: ‘it’ was not declared in this scope
       for (std::list<Tree<T>*>::iterator it = child.begin(); it != child.end(); it++)
                                                              ^~
    /home/evd/main2.cc:15:58: note: suggested alternative: ‘int’
       for (std::list<Tree<T>*>::iterator it = child.begin(); it != child.end(); it++)
                                                              ^~
                                                              int
    

    Ich muss gestehen ich stehe etwas auf dem Schlauch... die Liste ist doch vom Typ Tree<T>* ... und warum will er das vor dem std:: haben 😕

    wehre nett wenn ihr mir einen Ansatz geben könntet 🙂

    Grüße EvD



  • Benutze auto it = child.begin().
    Wie kommst du auf die Idee den Tree Destruktor aufzurufen?
    Wie kommst du auf die Idee delete this im Destruktor aufzurufen?



  • Faustregel: templates werden im Header implementiert.



  • Hallo

    Ich habe den Fehler jetzt so wie du es gesagt hast mit Auto korrigiert ... aber verstehe ich leider immer noch nicht was an meinem falsch war ... 😕

    Jetzt zu dem was manni66 noch gesagt hast:

    manni66 schrieb:

    Wie kommst du auf die Idee den Tree Destruktor aufzurufen?

    Habe ich jetzt auch geendert... wenn auch, glaube ich nicht wirklich besser xD ... wenn ich einen Knoten lösche, will ich auch alle untergeordneten Knoten löschen, damit ich nicht mit new Knoten angelegt habe die ich nicht wieder lösche und mein Speicher überfluten

    manni66 schrieb:

    Wie kommst du auf die Idee delete this im Destruktor aufzurufen?

    ich habe delete this zu delete *it zu machen, in der child schleife ... irgendwie alles komischer gemacht hat ...

    vielleicht wehret ihr so nett und könntet mir dabei auch noch helfen ... blicke gerade nicht so ganz durch xD

    Hier noch ein mal der etw neuere Code:

    Graph.h

    #include <iostream>
    #include <list>
    
    template<class T>
    class Graph
    {
    
    public:
    	T element;
    	std::list<Graph<T>*> childs;
    	std::list<Graph<T>*> parents;
    	Graph(T);
    	~Graph();
    	bool makeChild(Graph<T>*);
    	bool deleteChild(Graph<T>*);
    	bool makeParent(Graph<T>*);
    	T getElement();
    	bool leaf;
    };
    
    template<class T>
    Graph<T>::Graph(T element) : element(element)
    {
    	leaf = true;
    }
    
    template<class T>
    Graph<T>::~Graph()
    {
        if(!leaf)
            {
                for (auto it = childs.begin(); it != childs.end();)
    			{
    				// wenn das kind nicht mehrere Väter hat, denen ich es nicht weg nehmen will
    				if ((**it).parents.size()<2)
    				{
         				delete *it ++;
    				}
    				else{
    					it ++;
    				}
    			}
            }
    	if (!(*this).parents.empty())
        {
             for (auto it = parents.begin(); it != parents.end(); it++)
        	{
        		//alle Väter vergessen dieses Kind, damit es in ohne folgen beseitigt werden kann
        		(**it).deleteChild(this);
        	}
        }
    }
    
    template<class T>
    T Graph<T>::getElement()
    {
    	return (*this).element;
    }
    
    template<class T>
    bool Graph<T>::deleteChild(Graph<T>* tokill)
    {
    	for (auto it = childs.begin(); it != childs.end(); it++)
    	{
    		if( (*it)==tokill){
    			childs.erase(it);
    			return true;
    		}
    	}
    	// Error code hier einfügen
    	std::cout<<"Leider dieses Kind nicht gefunden. Error main2.h at line 61"<<std::endl;
    	return false;
    }
    
    //eingane der zu setzende Vater. Wenn setzen des Vaters gelingt, wird er in die Liste der Väter aufgenommen
    template<class T>
    bool Graph<T>::makeParent (Graph<T>* newParent){
    	if ((*newParent).makeChild(this)){
    		parents.push_back(newParent);
    		return true;
    	}
    	else{
    		//Error code hier einfügen
    		std::cout<<"das Erzeugen dieses Kindes bei dem Vater war nicht möglich. Error main2.h at line 76"<<std::endl;
    		return false;
    	}
    }
    
    template<class T>
    bool Graph<T>::makeChild(Graph<T>* inTree)
    {
    	childs.push_back(inTree);
    	(*inTree).parents.push_back(this);
    	leaf = false;
    	return true;
    }
    

    main.cc

    #include "Graph.h"
    #include <iostream>
    #include <string>
    #include <memory>
    int main (){
            {
                    int count = 0;
    /*				wenn new geht, wird das wieder aktiviert. solange inaktiv
                    std::shared_ptr<Graph<int>> test(new Graph<int>(5));
    */
         			Graph<int>* test = new Graph<int>(5);
                    for (int i = 0; i<2000000;i++){
                    (*test).makeChild(new Graph<int>(4));
                    (*test).makeChild(new Graph<int>(2));}
                    for (auto i = (*test).childs.begin(); i != (*test).childs.end() ;i++)
                    {
                            std::cout <<"Das Element " << (*test).getElement() << ":" << count << " ist " << (**i).getElement() << ". Ist es ein Blatt?: " << ((**i).leaf? "yes" : "no") << std::endl;
                            count ++;
                    }
                    count = 0;
                    delete test;
            }
    }
    

    Ich habe jetzt folgendes Problem ...
    Ich glaube ich lösche meinem Baum nicht vollständig ...
    Wenn ich einen Großen Tree erzeuge und ihn dann lösche, ist der Speicher im RAM aber immer noch belegt ... wenn ich diesen Baum aber noch ein mal erzeuge, wird der Belegte speicher nicht größer
    (z.b. while(true) schleife um alles, und die Zeile8-9 eine for 2 000 000 schleife)

    wie mache ich das richtig?
    also was habe ich da falsch gemacht?
    oder habe ich delete falsch verstanden?

    danke für eure Hilfe schon ein mal 🙂

    Grüße
    EvD

    EDIT: Leiche veränderungen im Code (ich hoffe das geht klar wenn ich die hier editiere und nicht immer wieder einen neuen Post auf mache) :
    -> umbenennung in Graph
    -> ein Kind fügt seinen Vater jetzt in die Parent liste ein (hups xD)
    -> Die Kinder werden alle aus der list child des Vaters gelöscht ... aber immer noch nicht aus dem Speicher 😕



  • aber verstehe ich leider immer noch nicht was an meinem falsch war ... 😕

    Eigentlich sagt die erste Fehlermeldung alles was es zu sagen gibt. Du musst dort typname benutzen.

    Ein Tree mit mehreren „Vätern“ finde ich seltsam. delete wirst du sicher nicht nur für ein Blatt aufrufen wollen.

    Benutze einen Debugger!



  • manni66 schrieb:

    Ein Tree mit mehreren „Vätern“ finde ich seltsam

    Da hast du wohl recht, ich habe es in "Graph" umgeändert der dann auch noch Gerichtet ist ...

    manni66 schrieb:

    delete wirst du sicher nicht nur für ein Blatt aufrufen wollen

    ich delete ja mit "delete *it" alle Kinder des Knoten.
    und mit "delete test" lösche ich ja auch den Knoten.

    Gedacht ist das ich mit delete knoten_A alles was unterhalb von knoten_A ist und knoten_A an sich lösche ... ich dachte das würde ich hier machen ... dachte ... denke ... 😕 😕

    Selbst mit dem Debugger komme ich bei dem delete Problem nicht weiter ...

    Weil anscheinend lösche ich mit delete *it original nichts ... was mich ein wenig verwirrt ...Ich rufe schon jedes "Blatt" auf ... weil ich für jeden Kind-Knoten delete aufrufe, und den pointer auf den Grapen<T> gebe, der gelöscht werden soll ... alles ein wenig komisch 😕

    Ich glaube das ich ein wenig verwirrt bin sieht man daran wie ich Texte schreibe 😕 😕

    Soll ich dafür ein neues Thema auf machen, oder kann man das noch hier drinnen beantworten?

    Grüße
    EvD



  • Wie ich gerade gesagt bekommen habe, soll ich nicht auf die RAM auslastung schauen, weil diese nicht aussagekräftig ist, sondern mit valgrind alles überprüfen ... und das hat mir dann gesagt das alles gut ist

    Daher (und deswegen dieser Doppel post) hat sich dieses Thema erledigt

    -> Gelöst <-


Anmelden zum Antworten