Kann sowas wahr sein???



  • Hallo zusammen!

    Also wenn das so weiter geht, werd ich wahrscheinlich niemals die STL benutzen.
    Überdenkt mal folgendes Beispiel:

    class Auto
    {
       public:
       Auto(){}
       ~Auto(){}
    
       virtual void fahre()=0;
    
       protected:
       private:
    };
    
    class Mercedes : public Auto
    {
       public:
       Mercedes(){}
       ~Mercedes(){}
    
       void fahre()
       {
           cout<<"brum brum"<<endl;
       }
    
       protected:
       private:
    };
    
    //-------------------------------------------------------------------------
    //Aber jetzt:
    
    hash_map<string,Auto> autoMap;
    autoMap["Meins"]=Mercedes();
    autoMap["Deins"]=Mercedes();
    (autoMap["Deins"]).fahre();
    
    ==> geht nicht, weil das idiotische Konzept der STL vorgiebt, dass sämtliche
        zu archivierenden ContentObjekte kopiert werden müssen.
        'autoMap' versucht demzufolge beim Archivieren Instanzen von 'Auto' zu
        kopieren.
    
    ==> Wenn ich damit richtig liege, heisst das:
        will ich mit der STL arbeiten, brauch ich Polymorphismus granicht erst 
        einzuplanen.
        (Ich könnte höchstens meine Autos dynamisch erzeugen und Pointer anstatt
         der gesamten Objekte archivieren ==> dann bin ich aber wieder für die
         Speicherverwaltung verantwortlich)
    

    So langsam reichts!!! 😡 Warum hab ich nur nicht weiterhin meine eigenen
    Containerklassen verwendet???? 😕

    Grüße,
    TS++



  • Polymorphie geht nur bei Objektzeigern, das liegt also nicht an der STL



  • die verschiedenen klassen sind doch auch verschieden groß. das würde so eh nicht klappen. probiers mal mit:

    hash_map<string,Auto*> autoMap; 
    autoMap["Meins"]=new Mercedes;
    autoMap["Meins"]->brenne();
    


  • TS++ schrieb:

    So langsam reichts!!! 😡 Warum hab ich nur nicht weiterhin meine eigenen
    Containerklassen verwendet???? 😕

    Die können das? 🙄



  • Die können das?

    Die arbeiten sofort mit dynamisch erzeugten Instanzen und Pointern, die darauf zeigen. Der wesentliche Unterschied zur Arbeit mit einer PointerHashMap der STL ist, dass mir meine eigene HashMap die Speicherverwaltung abnimmt. D.h.: wird z.B. die gesamte HashMap gelöscht, so werden auch alle darin verankerten ContentObjekte gelöscht. So wie's auch sein soll. Doch gearbeitet wird wirklich nur mit Pointern. Ich kann also damit problemlos Polymorphismus nutzen.

    Nicht wirklich weitsichtig von SGI! Etwas ernüchternd!

    Grüße,
    TS++



  • Du könntest ja einen smart_pointer in die Container packen, zum Beispiel den von boost(ich hab ihn mir noch nicht angeguckt, meine aber hier gelesen zu haben, dass es mit gehen soll).



  • TS++ schrieb:

    Die können das?

    D.h.: wird z.B. die gesamte HashMap gelöscht, so werden auch alle darin verankerten ContentObjekte gelöscht. So wie's auch sein soll.

    Warum sollte das _immer_ so sein? Sehr weitsichtig!



  • TS++ schrieb:

    Nicht wirklich weitsichtig von SGI! Etwas ernüchternd!

    nein, nicht weitsichtig von dir.

    nicht jeder zeiger zeigt auf speicher dem ihm gehoert.
    manchmal gehoert ihm der speicher naemlich nicht.

    du musst von der idee wegkommen das zeiger automatisch eine ressource darstellt. das tut er naemlich nicht.

    btw:
    binnen 5 minuten kann sich jeder einen wrapper um einen STL Container schreiben der die pointer gleich deleted wenn sie aus dem container geloescht werden.



  • @TS++: Nehmen wir mal an du hast eine ähnliche Klasse wie unten...

    // Pseudocode
    class Foo {
      string name;
      tsvector<Foo*> children;
      void foo();
    };
    

    Nun baust du dir eine Hierarchie auf...

    Beispiel: 
                Foo1
               /    \
          Foo1.1    Foo1.2
          /    \
    Foo1.1.1  Foo1.1.2
    

    Nun willst du Foo1.1.2 aber von Foo1.1 nach Foo1.2 verschieben. Was machst du? Richtig, du fügst Foo1.1.2 zu dem children-Vector von Foo1.2 hinzu. Naja, jetzt hast du aber einen doppelten Verweis. Was hast du vergessen? richtig, du musst Foo1.1.2 ja noch aus dem children-Vector von Foo1.1 löschen. _Deine_ Containerklasse gibt jetzt "praktisch" wie sie ist den Speicher frei. Du wanderst durch den Baum und rufst überall die Funktion foo auf... Crash... aber warum? Richtig, der Speicher wurde freigegeben. So ein Mist. Ab heute benutz ich wieder die STL weil die ja dem Anwender die Kontrolle über den Speicher überlässt.



  • OK, schließen wir nen Kompromiss! 😉

    Ich behaupte, dass sich die Einsatzgebiete für Container in 3 Bereiche aufsplitten lassen:

    +--------------------+-----------------+----------------------------+
       | intrinsische Werte |     Pointer     |          Objekte           |
       |    archivieren     |   archivieren   |        archivieren         |
       +--------------------+-----------------+-------------+--------------+
                                              |   Kopien    | Archivierung |
                                              | archivieren |    über      |
                                              |             |   Pointer    |
                                              +-------------+--------------+
    

    Wobei sich für die Archivierung von Objekten der bereits gegebene Ansatz der STL (also Archivierung von Kopien) und die bereits von mir genannte Vorgehensweise ergibt.
    (Wenn wir ehrlich sind, ist doch die Wahrscheinlichkeit für die Nutzung der Polymorphie bei der Arbeit mit Containern wahrscheinlicher, als der Fall, für den in der STL bereits Implementierungen existieren.

    Vorschlag:
    Der Kern der bisherigen STL könnte doch wunderbar für die reine Kopienorientierte Archivierung eingesetzt werden. Möchte ich allerdings Objekte archivieren und noch dazu nicht auf Polymorphismus verzichten, so wäre es doch mit Sicherheit sinnvoll, eine weitere Containerschicht anzubieten, die eine Ebene höher ansetzt, als die bisherigen Implementierungen der STL. Wobei auf dieser Schicht die Kernklassen der STL rein Pointerorientiert genutzt werden. (wie bereits beschrieben)

    Es macht sich doch kaum noch einer die Mühe alle BasisContainer selbst zu schreiben. Dafür gibt es ja die STL bzw. das STLPort. Eine Kapselung dieser Klassen auf höherer Ebene muss doch aber auch nicht immer wieder neu erfunden werden. Ist aber offensichtlich so. Denn die einzige Antwort, die die STL im Augenblick für diesen Problemfall bereithält ist: "selber schreiben!"
    Warum sollte man denn nicht weiterdenken?

    GRüße,
    TS++



  • TS++ schrieb:

    Die können das?

    Die arbeiten sofort mit dynamisch erzeugten Instanzen und Pointern, die darauf zeigen. Der wesentliche Unterschied zur Arbeit mit einer PointerHashMap der STL ist, dass mir meine eigene HashMap die Speicherverwaltung abnimmt. D.h.: wird z.B. die gesamte HashMap gelöscht, so werden auch alle darin verankerten ContentObjekte gelöscht. So wie's auch sein soll. Doch gearbeitet wird wirklich nur mit Pointern. Ich kann also damit problemlos Polymorphismus nutzen.
    Nicht wirklich weitsichtig von SGI! Etwas ernüchternd!

    ok.
    ähnliche gründe bewogen mich, bei meinem alten PtrHeap und Heap zu bleiben und nicht zu versuchen, alles in eine klasse zu mogeln. es muß nicht alles stl sein.



  • @volkard:

    sind PtrHeap und Heap zwei unabhängige Klassen oder ist PtrHeap mit Hilfe von Heap implementiert?



  • Shade Of Mine schrieb:

    @volkard:
    sind PtrHeap und Heap zwei unabhängige Klassen oder ist PtrHeap mit Hilfe von Heap implementiert?

    2
    wenn ich sie wiedermal anfassen muß, mach ich aber eine draus. normalerweis emüssen meine heaps nie löschen, falls ich doch mal nen löschenden brauche, kommt da ne löschpolicy rein und in dem zuge kann ich auch die beiden klassen zu einer machen.



  • Wenn man Polymorphie in Standardcontainern braucht, ist KPCs Vorschlag mit den Smart-Pointern imho die einfachste Lösung. boost::shared_ptr kann man bedenkenlos in einem oder mehreren Containern gleichzeitig verwenden. Man muss also nicht jeden Container neu für Pointer schreiben. Und außerdem:

    binnen 5 minuten kann sich jeder einen wrapper um einen STL Container schreiben der die pointer gleich deleted wenn sie aus dem container geloescht werden.

    So einfach ist das unter Berücksichtigung aller möglichen Exceptions imho auch wieder nicht... Da verlasse ich mich lieber auf die STL und boost, auch wenn der Referenzzähler in einigen Fällen vielleicht unnötiger Overhead ist.



  • operator void schrieb:

    So einfach ist das unter Berücksichtigung aller möglichen Exceptions imho auch wieder nicht... Da verlasse ich mich lieber auf die STL und boost, auch wenn der Referenzzähler in einigen Fällen vielleicht unnötiger Overhead ist.

    gib mal n beispiel wo das schwer ist...



  • Das Interface des Containers ist weniger das Problem. Aber wie will der Container z. B. das Leaken verhindern, wenn man z. B. std::remove() auf ihn anwendet? Und was macht er, wenn in einem anderen Algorithmus das Prädikat etwas wirft und ein Element doppelt im Container bleibt? (Bei std::sort könnte ich mir sowas vorstellen...)



  • wo soll bei remove das problem liegen?

    gerade bei remove() oder aehnlichem wird doch nix geloescht, sondern nur kopiert.
    das tut ja keinem weh (denn wenn da ne exception fliegt, muss es remove() ausbaden und nicht unser wrapper)

    gib mal n code beispiel wo wir nicht exception sicher sein koennen...



  • Eben, es wird kopiert, nicht geswappt. Nimm einen Vektor mit 10 ints:

    0123456789

    Wenn du dann remove(intvec.begin(), intvec.end(), 5) auf diesen Vektor anwendest, erhältst du (VC7.1):

    0123467899

    Auf Pointer umgedacht: Wenn du keine smarten Iteratoren verwendest, merkt der Container nichts davon, dass der Zeiger 5 verschwunden ist - Leak. Durch die anschließende Verkürzung des Vektors wird der Zeiger 9 doppelt gelöscht - Access Violation.

    (Hier braucht es nichtmals Exceptions, damit etwas schief geht. Aber mit Exceptions werden noch mehr Algorithmen gefährlich.)



  • ok, solche probleme hat man aber auch mit eigenen containern...

    btw: in diesem punkt verstehe ich den standard nicht.



  • Shade Of Mine schrieb:

    ok, solche probleme hat man aber auch mit eigenen containern...

    Aber nicht mit shared_ptr. Da können die Container und Algos praktisch nichts kaputt machen.

    Shade Of Mine schrieb:

    btw: in diesem punkt verstehe ich den standard nicht.

    Sie hätten shared_ptr nur mit reinnehmen sollen 😕



  • Hi!

    Für alle die sich damit rumplagen:
    Am WE ist mir diese Problemstellung auch untergekommen.
    Und zwar im Buch "Effectiv STL" von Scott Meyers.

    Sehr aufschlussreich und interessant geschrieben.

    Ich mache eigentlich keine Werbung, aber es passt einfach zu gut
    zu diesem Problem.

    Greetz
    Richie


Anmelden zum Antworten