global maps?!



  • Hi,

    ich deklariere in meinem Header folgende map:

    class A;
    class Class
    {
    public:
        map<string, A*> test_map;
        void f();
    };
    

    Nun versuche ich innerhalb der Methode f, in diese map zu schreiben:

    void Class::f()
    {
       A inst= A();
       A.SetName("Name");
       test_map.insert(pair<string, A*>(inst.GetName(), &inst));
    }
    

    Beim Debuggen muss ich aber feststellen, dass die map nach dem Aufruf von insert, immer noch leer ist.
    Testweise habe ich dann eine map innerhalb meiner Methode f() deklariert und in diese geschrieben. Das hat auch funktioniert. Anschließend habe ich versucht mit Hilfe der swap() Funktion der map, die Inhalte der beiden maps aus zu tauschen. Danach enthalten beide maps keine Elemente mehr. Also scheinbar kann ich die map nicht beschreiben... aber wieso?



  • Sehe ich das richtig, dass "A" der Name deiner Klasse ist und du versuchst von dem eine Memberfunktion aufzurufen, ohne ein Objekt der Klasse erzeugt zu haben?

    Dein Compiler übersetzt den Code?



  • Also bei mir ist die map nicht leer. Das Problem ist, dass inst ein lokales Objekt ist und bei Verlassen von f gelöscht wird. In der map hast du dann einen Zeiger auf ein A, dass gar nicht mehr existiert.



  • @DerLaberkopp:
    Sorry da war ein Fehler in dem geposteten Code ;-).

    @brotbernd:
    Also laut meinem Debugger ist die Map definitiv leer. Der insert wird zwar aufgerufen, aber danach herrscht immer noch gähnende Leere in der map...

    Aber das mit dem lokalen Objekt sehe ich ein:

    class A;
    class Class
    {
    public:
        map<string, A*> test_map;
        void f();
        A* inst;
    };
    
    void Class::f()
    {
       for (...) //soll nur eine mehrfache Wiederholung andeuten
       {
          inst = new A();
          inst->SetName("Name");
          test_map.insert(pair<string, A*>(inst->GetName(), inst));
       }
    }
    

    Aber immer noch das gleiche Ergebnis.



  • Poste mal den richtigen Code, und nicht irgendein Beispiel.



  • Der richtige Code ist einfach zu lang und ich habe das ganze eben auf das runter abstraktiert...! Ansonsten dürften keine Codeschnipsel mehr eine Rolle spielen...

    class A ist auf jeden Fall nicht abstrakt, statisch oder sonstiges... Ich denke der Fehler sollte in den wenigen Zeile schon drin stecken?!



  • Nicht denken, überprüfen. Kompilier den Code den du hier reinschreibst und wir diskutieren über das Verhalten dieses Codes, nix anderes.



  • class A;
    class Class
    {
    public:
        map<string, A*> test_map;
        void f();
        A* inst;
    };
    class A
    {
        string Name;
        const string& GetName() const
        {
            return Name;
        }
        void SetName(const string& NameNew)
        {
            Name = NameNew;  
        }
    
        A(){}
    };
    
    void Class::f()
    {   
       for(int i =0; i< 5; i++)
       {
          inst = new A();
          inst->SetName("Name");
          test_map.insert(pair<string, A*>(inst->GetName(), inst));
       }
    }
    

    Compiliert und lauffähig. Leider wird in meine test_map trotz des insert keine Daten geschrieben!?



  • Kompiliert bei mir nicht, denn A hat einen privaten Konstruktor. Copy&Paste kann doch nicht so schwer sein oder?



  • Ja tut mir Leid, aber bei den riesigen Klassen, habe ich leider das public vergessen zu kopieren (steht eben ganz oben...)

    class A;
    class Class
    {
    public:
        map<string, A*> test_map;
        void f();
        A* inst;
    };
    class A
    {
    public:
        string Name;
        const string& GetName() const
        {
            return Name;
        }
        void SetName(const string& NameNew)
        {
            Name = NameNew;  
        }
    
        A(){}
    };
    
    void Class::f()
    {  
       for(int i =0; i< 5; i++)
       {
          inst = new A();
          inst->SetName("Name");
          test_map.insert(pair<string, A*>(inst->GetName(), inst));
       }
    }
    


  • Hast du wirklich geprüft, ob dieser Code den Fehler überhaupt reproduziert?

    Kann es sein, dass du (in deinem echten Code) mehrere Instanzen von Class erzeugst?



  • Bei mir hat test_map einen Eintrag.
    Warum es nur einer ist und nicht fünf (Schleife wir ja 5 mal durchlaufen) ist dir klar?



  • Mein Debugger ist scheinbar schrott... offenbar sind Einträge vorhanden, die jedoch nicht vom Debugger angezeigt werden! Ich habe nach der for Schleife folgendes gemacht:

    string c = "Name";
    //test_map.count(c);
    if (test_map.count(c)>0)
    {
    	printf("\nWelcome ist drin!\n"); //Code wird erreicht, also ist Welcome drin!
    }
    

    Also zeigt der Debugger den Inhalt der map nicht an, aber es ist was drin. Trotzdem kann ich die in der Map gespeicherten Daten nicht "verwenden". Also Klasse A ist irgendwie nicht "funktionsfähig".

    @inter2k3:
    Ehrlich gesagt ist mir nicht so richtig klar, warum es nur einen Eintrag gibt?! Weil es nur eine Instanz von A gibt, die dann immer überschrieben wird?



  • Max064 schrieb:

    Weil es nur eine Instanz von A gibt, die dann immer überschrieben wird?

    Nein, weil es 5 Instanzen gibt, die aber alle als Name "Name" drin haben. Und da die map für einen key immer nur ein value haben kann, wird beim insert ab dem zweiten A immer ein neues Objekt als value für den selben key reingehängt.

    Welche IDE bzw. welchen Compiler und welchen Debugger verwendest du?



  • Ich verwende Visual Studio 2008 SP1...

    Entstehen dann so 5 Enträge? Mein Debugger zeigt immer noch keinen an...

    void Class::f()
    {  
       string text;
       text = "Name";
       for(int i =0; i< 5; i++)
       {
          inst = new A();
          inst->SetName(text);
          text = text + "neu";
    
          test_map.insert(pair<string, A*>(inst->GetName(), inst));
       }
    }
    


  • Max064 schrieb:

    Entstehen dann so 5 Enträge?

    Ja.



  • also ich habs mal so debuggt:

    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    class A;
    class Class
    {
    public:
        map<string, A*> test_map;
        void f();
        A* inst;
        ~Class();
    };
    class A
    {
    public:
        string Name;
        const string& GetName() const
        {
            return Name;
        }
        void SetName(const string& NameNew)
        {
            Name = NameNew;  
        }
    
        A(){}
    }; 
    
    void Class::f()
    {  
       string text;
       text = "Name";
       for(int i =0; i< 5; i++)
       {
          inst = new A();
          inst->SetName(text);
          text = text + "neu";
    
          test_map.insert(pair<string, A*>(inst->GetName(), inst));
       }
    }
    
    Class::~Class()
    {
       for (map<string, A*>::iterator it = test_map.begin(); it != test_map.end(); ++it)
       {
          delete it->second;
       }
    }
    
    int main()
    {
       Class c;
       c.f();
    }
    

    wenn man nach dem Aufruf von c.f() in den Debugger schaut sollte es in etwa so aussehen: http://www.image-load.net/page.php?type=jpg&f=c0aa0d5bb61add46b09675b97b058934



  • pumuckl schrieb:

    Class::~Class()
    {
       for (map<string, A*>::iterator it = test_map.begin(); it != test_map.end(); ++it)
       {
          delete it->second;
       }
    }
    

    Was genau bewirkt der Destruktor? Brauch ich den?

    Mein Debugger zeigt immer noch 0 Elemente an, aber mittlerweile kann ich die Objekte in der map, die laut Debugger nicht mal vorhanden sind ;-), benutzen...



  • Max064 schrieb:

    Was genau bewirkt der Destruktor? Brauch ich den?

    Der bewirkt, dass der Speicher, den du mit new angefordert hast, auch wieder freigegeben wird.
    Ist aber nur sehr murkelig implementiert, da z.B. bei dem schon dagewesenen Fall, dass der key bereits in der map vorhanden war, immernoch Speicherlecks entstehen.



  • Du solltest besser die Objekte selbst in die map stopfen, nicht die Zeiger darauf. Dann werden sie auch von der Map verwaltet und sie gehen zusammen mit der Map unter...


Anmelden zum Antworten