Frage zu auto_ptr und map der STL



  • Smartpointer klingen gut, aber std::auto_ptr ist im Zusammenhang mit STL-Containern nicht verwendbar (der Elementtyp muß kopierbar sein und das erfüllt auto_ptr nicht - der würde dir jedes Mal, wenn die Elemente umgeordnet werden müssen, deine Daten vernichten). Schau dich mal nach boost::shared_ptr (bzw. sein TR1-Äquivalent) um, der ist hierfür besser geeignet.

    (PS: Und schau mal in unser Magazin vorbei, dort gibt es u.a. einen Artikel zum Thema Smart-Pointer)



  • Wow, das ging aber schnell, ich bin begeistert 🙂

    Vielen Dank für die Antworten, ich werde also das ganze ersteinmal mit "normalen" Pointern erledigen und die Objekte in der map - falls die map nicht mehr vonnöten ist - mit delete löschen. Andere Lösungen werde ich vorerst verschieben, bis ich mit den c++ - Grundlagen und der STL einigermaßen klar komme.

    Danke nochmals 🙂



  • Möchte darauf hinweisen, das du nur bei Polymorphie Pointer in deinem Container anlegen mußt. Sind die Objekte dagegen immer vom gleichen Typ, legst du halt keine Pointer an sondern den Typ selbst:

    map<int, MeineKlasse> MeineMap;
    

    Dann brauchst du auch kein new und kein delete.



  • Artchi schrieb:

    Möchte darauf hinweisen, das du nur bei Polymorphie Pointer in deinem Container anlegen mußt. Sind die Objekte dagegen immer vom gleichen Typ, legst du halt keine Pointer an sondern den Typ selbst:

    map<int, MeineKlasse> MeineMap;
    

    Dann brauchst du auch kein new und kein delete.

    Stimmt auf jeden Fall ... allerdings lohnt es bisweilen bei "großen Objekten" (und die hat der OP hier IIRC) und viel Einfügen/Löschen" auch, weil man sich sonst schnell mal "totkopiert".
    Vielleicht sollte man da aber auch erstmal "normal" anfangen und bei den ersten Tests feststellen, wieviel das wirklich ausmacht - Stichwort: "Avoid premature optimization" 😃

    Gruß,

    Simon2.



  • Möchte darauf hinweisen, das du nur bei Polymorphie Pointer in deinem Container anlegen mußt. Sind die Objekte dagegen immer vom gleichen Typ, legst du halt keine Pointer an sondern den Typ selbst:

    Ich weiß nicht ob ich das nun 100%ig verstanden haben:
    In meinem Beispielprogramm nutze ich für die Klasse MeineKlasse keine Polymorphie, allerdings möchte ich die Objekte der Klasse im Heap speichern.
    Wenn ich nun in der map keinen Pointer auf MeineKlasse benutze - werden dann die Instanzen nicht im Stack abgelegt ?
    Und wie kann/muss ich die dann benutzen (so dass sie auf dem Heap liegen)?

    Mit Zeiger:

    {
    map<int, *MeineKlasse> MeineMap;
    
    //ein Objekt von MeineKlasse erstellen
    MeineKlasse* pObj = New MeineKlasse(parameter);
    map[3] = pObj;
    
    // viel Code...
    
    // Löschen der Objekte aus dem Heap:
        map<int, *MeineKlasse>::iterator iter;
        for(iter = MeineMap.begin(); iter != MeineMap.end(); iter++)
        {
            delete iter->Second;
        }
    } /* Gültigkeitsbereich von MeineMap verlassen, Speicher in Heap muss freigegeben sein */
    

    Ohne Zeiger:

    //???
    


  • Illarion schrieb:

    ...
    In meinem Beispielprogramm ...möchte ich die Objekte der Klasse im Heap speichern....

    => Du musst Pointer verwenden.
    Artchi wollte aber darauf hinweisen, dass es evtl. gar nicht nöig ist, die Objekte auf den Heap zu legen.

    Gruß,

    Simon2.



  • Naja, kommt darauf an, was große Objekte sind? (vielleicht denkt er, die seien groß, und in Wirklichkeit langweilt sich die Runtime) Und wie oft wird etwas eingefügt? (gehts in dem Container wild und heiß her?) Also ich vermeide immer Pointer in Containern. Wenn ich weiß, das es in dem Container wild zu geht, mach ich mir schon Gedanken.



  • Ohne Pointer:

    map<int, MeineKlasse> MeineMap;
    
    //ein Objekt von MeineKlasse erstellen
    MeineKlasse pObj(parameter);
    map[3] = pObj;
    
    }
    


  • Ok, vielen Dank euch allen für die nette, kompetente und schnelle Hilfe 🙂

    Später werde ich mir hierfür noch andere SmartPointer ansehen, die das delete übernehmen und auch im Fall auftretender Exceptions den Speicher freigeben, vorerst ist es so aber völlig ausreichend 😉

    @Artchi: Die Objekte sind de facto nicht Groß, mir geht es eher um das Theoretische, das Gewusst-Wie 😉 Ich habe ja erst vor ner knappen Woche mit C++ angefangen.



  • Artchi schrieb:

    Naja, kommt darauf an, was große Objekte sind? (vielleicht denkt er, die seien groß, und in Wirklichkeit langweilt sich die Runtime)...

    Deswegen meinte ich ja: Erstmal testen (und bis zum Beweis des Gegenteils davon ausgehen, dass es kein Problem ist mit Stackobjekten)! Vorher weiß man's nicht wirklich.
    Etwas Anderes ist es noch, wenn man externe Ressourcen (Files, Connections, ...) verwaltet. In dem Fall kann das Kopieren einerseits konzeptionell als auch performancetechnisch ein Problem darstellen...
    Aber das sind eher seltene Ausnahmen.

    Gruß,

    Simon2.



  • Illarion schrieb:

    Ok, vielen Dank euch allen für die nette, kompetente und schnelle Hilfe 🙂

    Später werde ich mir hierfür noch andere SmartPointer ansehen, die das delete übernehmen und auch im Fall auftretender Exceptions den Speicher freigeben, vorerst ist es so aber völlig ausreichend 😉

    Hi,

    dafür brauchst Du nicht unbedingt smart_pointer.
    Es genügt, im Dtor des "Verwaltungsobjekts" (das die map beinhaltet und in dem die map gefüllt wird) die map durchzugehen und die Objekte zu deleten..

    Gruß,

    Simon2.



  • Simon2 schrieb:

    dafür brauchst Du nicht unbedingt smart_pointer.
    Es genügt, im Dtor des "Verwaltungsobjekts" (das die map beinhaltet und in dem die map gefüllt wird) die map durchzugehen und die Objekte zu deleten..

    Gruß,

    Simon2.

    Genau so habe ich es nun auch gelöst 🙂

    Wow C++ fängt an richtig Spaß zu machen. Aber der OOP-Ansatz ist wirklich eine riesige Umstellung zu Basic/Pascal... (eben was ich vorher benutzt habe)



  • Illarion schrieb:

    ......
    Wow C++ fängt an richtig Spaß zu machen....

    😋 Oh Ja !! 😋 *schwärm* 👍

    Also ich finde, dass Du ganz gut auf dem Weg bist und habe nicht den Eindruck, dass Du Dich mit dem Umstieg besonders schwer tätest !

    Weiter so !! 😃

    Gruß,

    Simon2.



  • Wenn man die Standardlibrary benutzt und kennt, macht C++ auch Spaß. 🙂 👍



  • Hierzu noch:

    Simon2 schrieb:

    Illarion schrieb:

    ...
    In meinem Beispielprogramm ...möchte ich die Objekte der Klasse im Heap speichern....

    => Du musst Pointer verwenden.

    Landen die Objekte die die map allokiert etwa auf dem Stack? Und wenn ja, wie macht die map das bloss? 😉

    Was ich damit sagen will, die Container der Standardbibliothek verwalten den Speicher den ihre Mitglieder zweifellos brauchen doch auch (irgendwo) auf dem Heap, nur dass der Benutzer eben nicht mit new und delete in Kontakt kommt...



  • LordJaxom schrieb:

    Was ich damit sagen will, die Container der Standardbibliothek verwalten den Speicher den ihre Mitglieder zweifellos brauchen doch auch (irgendwo) auf dem Heap, nur dass der Benutzer eben nicht mit new und delete in Kontakt kommt...

    Hi, also wenn das stimmt, dann würde ich tatsächlich nur einen Pointer brauchen, wenn ich Polymorphie nutze (wegen der automatischen Typbestimmung und Funktionszuordnung durch die vtable - wenn ich das richtig verstanden habe).

    Und wenn ich ein Objekt erstelle... (also bei Verwendung OHNE Zeiger, da keine Polymorphie)

    //ein Objekt von MeineKlasse erstellen
    MeineKlasse Obj(parameter);
    map[3] = Obj;
    

    ... wird also folglich der Kopierkonstruktor aufgerufen um das Objekt Obj zu kopieren und - verwaltet durch die Contaninerklasse map - auf dem Heap abzulegen. new / delete übernimmt map, ich brauche mich darum nicht zu kümmern.

    Ist das nun so richrig 😕



  • LordJaxom schrieb:

    ...
    Landen die Objekte die die map allokiert etwa auf dem Stack? Und wenn ja, wie macht die map das bloss? ;)...

    template <typename keyT, typename valT>
    class myMap {
       pair<keyT, valT> static_vals[MAX_SIZE];
       pair<keyT, valT> vals;
       size_t size;
    public:
       myMap() vals(static_vals), size(0) {}
    ...
    

    :p

    Aber stimmt schon: Es ist weder besonders wahrscheinlich noch wirklich sinnvoll, dass es so gemacht wird (außer vllt. für kleine Eintragszahlen und ab einer gewissen Größe schwenkt er dann auf den Heap ... aber auch nicht besonders wahrscheinlich)...

    Mein Schwerpunkt bei der Aussage war: Er wollte gerne (außerhalb der map) mit Heapobjekten hantieren (jedenfalls habe ich ihn so verstanden) ...

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Mein Schwerpunkt bei der Aussage war: Er wollte gerne (außerhalb der map) mit Heapobjekten hantieren (jedenfalls habe ich ihn so verstanden) ...

    Wenn ich mich da jetzt mal drauf versteifen darf, dass mit "hantieren" nicht zwangsläufig new/delete gemeint ist: Geht doch auch so, solang das Objekt in der Map noch existiert

    map<int, string> names;
    names[10] = "Sascha";
    string* p = &names[10]; // <- Zeiger auf Objekt auf Heap, vorausgesetzt die Map nutzt den Heap, was wie bereits festgestellt ist der wahrscheinlichste Fall sein dürfte.
    

    @Simon2:
    Aber nimm mich bitte nicht zu ernst 🤡

    @Illarion:
    Den äußerst unwahrscheinlichen Fall, dass die Map so wie von Simon skizziert angelegt ist, mal aussen vor gelassen, ist das so richtig 😉



  • Simon2 schrieb:

    Mein Schwerpunkt bei der Aussage war: Er wollte gerne (außerhalb der map) mit Heapobjekten hantieren (jedenfalls habe ich ihn so verstanden) ...

    Vielleicht habe ich mich doch nicht deutlich genug ausgedrückt.

    Die Objekte müssen nur "in der map liegen", also von außerhalb der map soll erst gar nicht auf diese Objekte zugegriffen werden. Jedoch ist es wichtig, dass die Objekte sich im Heap befinden.

    *Uff* anstrengend - alles Neuland für mich, meine Kentnisse beruhen auf c++ - Tutorials wie Schornboeck und Volkards C++ Kurs.

    Ich hoffe ich habs nun soweit alles verstanden^^



  • Jedoch ist es wichtig, dass die Objekte sich im Heap befinden.

    Warum?


Anmelden zum Antworten