Pointer auf Elemente von STL Containern?



  • Kleine Frage: Wenn ich einen Pointer auf ein Element anlege, das in einem STL-Container liegt, ist der Pointer dann immer gueltig (natuerlich vorausgesetzt, ich loesche das Element nicht).

    Ich moechte in einem "Sammelbehaelter" eine Reihe Elemente Sammeln und in diversen anderen Objekten Referenzen oder Pointer auf diese Elemente verwalten.

    /edit: mir faellt grade auf dass die meisten der gesammelten Objekte keine Datenmember haben und nur aus virtuellen Funktionen bestehen - also sollte ich sie wohl besser einfach kopieren. Selbst wenn die Dinger mal 8 byte gross werden ist das ja nicht so unheimlich tragisch...



  • Klingt nach nem komplizierten Entwurf den man einfache rmachen könnte.



  • Pointer sind ne schlechte Idee (auch wenn es sogar funktionieren
    dürfte solang sich die Größe des Containers nicht ändert).

    Benutzte stattdessen Iteratoren, das STL-Pendant zu Pointern.



  • Das hängt ganz von dem verwendeten Container ab - list<> und die assoziativen Container sichern zu, daß Pointer und Referenzen gültig bleiben, solange ihr Ziel noch im Container liegt. deque<> und vector<> dürfen bei Einfüge- und Lösch-Operationen auch Pointer ungültig machen, die mit der Aktion eigentlich nichts zu tun haben (wenn du mitten im Container ein Element löschst, muß die Lücke wieder gefüllt werden, indem Elemente vom Ende her nachgeschoben werden).



  • Storm.Xapek.de schrieb:

    Pointer sind ne schlechte Idee (auch wenn es sogar funktionieren
    dürfte solang sich die Größe des Containers nicht ändert).

    Benutzte stattdessen Iteratoren, das STL-Pendant zu Pointern.

    Ja und genau über die Gültigkeit von Iteratoren sagt der Standard ja was aus.
    Und da Zeiger auch nicht mehr können als Iteratoren, werden Zeiger (spätestens) dann ungültig, wenn auch der entsprechende Iterator ungültig würde.

    Ergo: Iterator nehmen und Gültigkeit beachten. (Machen die Iteratoren nicht selbst !)

    Gruß,

    Simon2.

    P.S.: Für nicht wenige Situationen dürften Iteratoren "hinter den Kulissen" sowieso Pointer sein.



  • Hintergrund ist folgender:

    Ich habe eine Klasse "Instruction" bei der jedes Objekt eine bestimmte Aktion Kapseln soll. Diee hat zwei Unterklassen, naemlich zusammengesetzte Aktionen und Einzelaktionen. In den zusammengesetzten Aktionen moechte ich irgendwie eine Liste von Verweisen auf Einzelaktionen und weitere zusammengesetzte Aktionen speichern, die dann bei Ausfuerung der zusammengesetzten Aktion nacheinander abgeklappert werden.
    Wegen der Polymorphie kann ich in den Containern nur Referenzen bzw. Zeiger auf "Instruction" speichern und muss daher die eigentlichen Objekte woanders ablegen.

    pseudocode zum Veranschaulichen:

    struct Instruction {
      virtual void exec() = 0;
    };
    
    struct basic1 : public Instruction {
      virtual void exec() 
      { //...
      }
    };
    
    struct basic2 : public Instruction {
      virtual void exec() 
      { //...
      }
    };
    
    class ComposedInstruction : public Instruction {
      std::list<Instruction*> instructions;  //wird fuer jedes Objekt irgendwo zusammengebaut...
    
      virtual void exec() {
        for(iter = instructins.begin(); inter != instructions.end(); ++iter)
         (*iter)->exec();
      }
    };
    
    int main() {
     ComposedInstruction foo;
     //zusammenbauen
     foo.instructions.push_back(new basic1);
     foo.instructions.push_back(new basic2);
     foo.instructions.push_back(new basic1);
    
     foo.exec();
    }
    


  • HI,

    ach, dann machst Du ja gar nicht, was ich (und wohl auch andere hier vermutete) !!

    Das, was Du da zeigst, ist ein Container mit Pointern.
    Unter "Pointer auf Elemente von Containern" hätte ich Folgendes verstanden:

    vector<int> vec(3);
       int* p = &vec[1];
       // ...(*)
       cout << *p;
    

    Das kann (wie oben beschrieben) übelst in die Hose gehen, wenn bei (*) der vector verändert (und dadurch sein Inhalt woanders hin verschoben) wird.
    Das, was Du beschreibst ist vollkommen problemlos und sicher: Du greifst via iterator zu und holst sie auch immer wieder neu...

    Gruß,

    Simon2.



  • Args. Nee mein Denkfehler war noch ein ganz anderer. Ich hatte ueberlegt, statt die einzelnen Instructions mit new zu erzeugen, sie in einen globalen Container zu schmeissen und dann in den listen Zeiger auf die Instructions in eben diesem globalen Container abzulegen. (Von daher war meine Frage nach der Gueltigkeit der Zeiger schon richtig). Wegen der polymorphie muss ich aber auch in dem globalen Container mit Zeigern arbeiten, weshlab sich das dann wieder eruebrigt. (Nichtdestotrotz eine Frage die mich eh schon immer interessiert hat)

    int main()
    {
    std::map<std::string, Instruction*> allInstr;
    allInstr.insert("basic1", new basic1);
    allInstr.insert("basic2", new basic2);
    
    {
     ComposedInstruction* foo = new ComposedInstruction;
     //zusammenbauen
     foo->instructions.push_back(allInst["basic1"]);
     foo->instructions.push_back(allInst["basic2"]);
     foo->instructions.push_back(allInst["basic1"]);
     allInstr.insert("FOO", foo);
    }
    
    allInstr["FOO"]->exec();
    
    //...
    //am Ende for (everything in allInst) delete...
    }
    

Anmelden zum Antworten