Implementierung von operator=() mit Deep Copy einer dynamischen Liste


  • Mod

    Oder nimm keine Liste, sondern was flottes.



  • heimchen schrieb:

    Über den operator= möchte ich nun eine Kopie meiner Klasse:

    Bei einer Klasse wie dieser, ist es angebracht, den Zuweisungsoperator so zu definieren:

    DeineKlasse& operator=(DeineKlasse temp)
          {
            this->swap(temp); // Dieser Trick nennt sich
            return *this;     // "Copy-and-Swap", temp ist die Kopie
          }
    

    Dazu benötigst Du natürlich einen funktionierenden Kopierkonstruktor (für temp) und eine entsprechende swap-Funktion (da kannst Du dann einfach intern zwei Zeiger vertauschen oder sowas). Dazu solltest Du dann noch

    inline void swap(DeineKlasse& a, DeineKlasse& b)
    { a.swap(b); }
    

    als freie Funktion in demselben Namensraum anbieten, damit sie per ADL aka Koenig Lookup erreichbar ist.

    Du kannst es Dir natürlich wesentlich einfacher machen, indem Du "richtig" C++ programmierst (im Sinne von effektiver Nutzung der Dir zur Verfügung stehenden Mittel):

    class NochNeKlasse
    {
      std::list<int> intliste_;  // oder doch besser std::vector<int> ?
      int a,b,c;
    public:
      …
    };
    

    Hier ist kein von Hand geschriebener Kopierkonstruktor, Destruktor oder Zuweisungsoperator nötig. Das kommt daher, da std::list<> schon Deine gewünschte Kopiersemantik besitzt und nicht nur ein dämlicher Zeiger ist. Die für NochNeKlasse generierten Kopieroperationen des Compilers "kopieren" auch nur die Datenelemente. Und was "Kopieren" bei std::list heißt, wird ja in dem Kopierkonstruktor der std::list definiert.

    heimchen schrieb:

    Was mach ich falsch?

    Du programmierst drauf los. Kapselung geht in C++ viel weiter als in C. C++ erlaubt Dir einfach zu benutzende Typen und Typfamilien selbst zu definieren (inklusive eigener Erzeuge-, Zerstör- und Kopier-Semantik). Einiges von solchen Typen hält die Standardbibliothek bereit. Nutze sie. Das heißt aber nicht, dass Du bei allen Deinen Klassen, Kopierkonstruktor, Destruktor etc selbst definieren musst. Versuche, sie korrekt vom Compiler generieren zu lassen und nur für die kleinsten Bausteine selbst zu definieren, falls nötig. Ein wichtiges Designprinzip ist, dass sich eine Klasse (in Form von selbst geschriebenen Verwaltungsoperationen a la Kopierkonstruktor etc) nur um höchstens eine Ressource kümmern sollte. Wenn Du also irgendwann zwei Listen brauchen solltest, dann wär es extrem praktisch, das Konzept "Liste" als eigenen Typ vorrätig zu haben, statt dass die Klasse, die 2 Listen benötigt, alles selbst machen muss…



  • DocShoe schrieb:

    Da du keinen Kopierkonstruktor für deine Klasse hast werden die Elemente bitweise kopiert.

    Bei dieser Klasse, ja. Im Allgemeinen werden die Datenelemente "kopiert", wobei "kopieren" das ist, was der entsprechende Typ des Datenelements definiert — also nicht unbedingt bitweise…



  • Ok, ich hab jetzt QList genommen, war schon recht bequem 😉
    Jetzt stürzt auch mein Programm nicht mehr ständig ab. Hatte den Destruktor nicht im Blick, der mir die Listenelemente gelöscht hat. Und wenn das schon bei der Kopie passiert ist, gibt das komische Effekte beim Original...

    bmario schrieb:

    Du regst dich auf, dass du immer die gleichen Sachen per Hand machen musst, aber willst selber eine Liste programmieren? 😮

    Mit "von Hand" meinte ich tatsächlich von Hand, also einmal Daten in ein Programm eingeben und ein zweites Mal die gleichen Daten in ein anderes Programm eingeben. Das Programmieren einer eigenen Liste ist dazu schon ein immenser Fortschritt. Abgesehen davon find ich das auch ganz interessant.



  • Wie man eine ordentliche einfach verkettete Liste implementiert, siehst du hier: http://www.c-plusplus.net/forum/p2156719#2156719



  • Habs jetzt nur mal überflogen, aber dort ist auch kein Kopierkonstruktor drin. Da dürfte es ähnliche Probleme geben, wie bei mir.
    Abgesehen davon gehören Listen ja auch zum Lehr-Standard in Schule und Uni, also im Prinzip weiß ich, wie's geht. Probleme machen ja erst die eigenen Spezialitäten.



  • Ist er wohl. Lern lesen.



  • 314159265358979 schrieb:

    Wie man eine ordentliche einfach verkettete Liste implementiert, siehst du hier: http://www.c-plusplus.net/forum/p2156719#2156719

    So toll finde ich die jetzt nicht. Mich stört, dass da immer -- auch bei einer leeren Liste -- zwei T-Objekte erzeugt werden und T dementsprechend default-konstruierbar sein muss.

    Vielleicht könnte man das noch mit Vererbung so lösen

    struct list_link
    {
      list_link* next;
    
      explicit list_link(list_link* n = 0)
      : next(n)
      {}
    
      list_link(list_link const&) = delete;
      list_link& operator=(list_link const&) = delete;
    };
    
    template<class T>
    struct list_node : list_link
    {
        T value;
    
        list_node* next() const {return static_cast<list_node*>(list_link::next);}
        void next(list_node* n) {list_link::next = n;}
    
        template<class...Args>
        explicit list_node(list_node* n, Args&&...args)
        : list_link(n)
        , value(std::forward<Args>(args)...)
        {}
    };
    

    und dann liste so aufbauen:

    template<class T>
    class list
    {
      list_link  before_begin_;
      list_link *before_end_ptr_; // fuer schnelles push_back
    public:
      list()
      : before_begin_(/* mit next= */ 0)
      : before_end_ptr_(&before_begin_)
      {}
      ...
    };
    

    Die Verkettungsoperationen (Knoten löschen, einfügen, etc) könnte man auch auf Basis von list_link definieren, weil diese Funktionen ja auch nicht von T abhängen. Hier und da müsste man ggf noch static_cast<node<T>*> auf einen next-Zeiger anwenden. Das ist aber IMHO vertretbar; denn in diesem Design würde jeder next-Zeiger garantiert auf ein node<T>-Objekt zeigen (oder 0 sein).

    Ach, ist "last" wirklich nötig? Das Ding scheint mir im Moment sehr nutzlos zu sein, zumindest bei einer einfach verkettenen Liste.
    Edit: Ok, das weißt Du schon, sehe ich gerade.

    list_link* remove_link(list_link* predecessor) {
      list_link* removed = predecessor->next;
      predecessor->next = removed->next;
      removed->next = 0;
      return removed;
    }
    

    oder so...

    (alles ungetestet)

    Cheers!
    kk

    P.S.: Sei mal nicht so patzig. Der Überlegenheitskomplex steht Dir nicht. :-p
    😉



  • Ist lesen denn so schwer? Meine Fresse.



  • 314159265358979 schrieb:

    Ist lesen denn so schwer? Meine Fresse.

    Nö. Habe keine Lust den kompletten Fred zu lesen. Du verlinkst auf Deine Liste. Die habe ich kritisiert. Nichts ist daran verwerflich. Sollte da am Ende des Freds noch eine andere bessere Implementierung stehen, hättest Du die ja verlinken können...

    Falls ich mich jetzt zu unrecht angesprochen gefühlt habe: Ja, den Kopierkonstruktor kann man schonmal übersehen -- gerade dann, wenn er nicht auf dieser Seite sondern auf einer der folgenden kommt. Das ist kein Grund so pampig zu werden, meiner Meiung nach.



  • Wenn 2 Leute hintereinander ganz offensichtlich nicht lesen können...



  • 314159265358979 schrieb:

    Wenn 2 Leute hintereinander ganz offensichtlich nicht lesen können...

    Und wenn du nur einen funken intelligenz hättest...



  • 314159265358979 schrieb:

    Wenn 2 Leute hintereinander ganz offensichtlich nicht lesen können...

    Du trollst doch nur rum, gerade. Das ist mir jetzt nicht mehr als 2 Sätze wert.



  • Bin ich der einzige, den ein (temporärer) pi-Bann nicht stören würde?



  • DocShoe schrieb:

    Bin ich der einzige, den ein (temporärer) pi-Bann nicht stören würde?

    Gabs schon, hat offenbar nicht viel bewirkt. Werden es aber weiterhin im Auge behalten. Bitte zurück zum Thema und bitte auf den Ton achten, und zwar alle.



  • krümelkacker schrieb:

    Nö. Habe keine Lust den kompletten Fred zu lesen.

    Es hätte gereicht, wenn du den kompletten Post gelesen hättest. Dann wüsstest du nämlich, dass es eine Fortsetzung gibt.

    krümelkacker schrieb:

    Sollte da am Ende des Freds noch eine andere bessere Implementierung stehen, hättest Du die ja verlinken können...

    Willst du ernsthaft, dass ich mir dir Arbeit mache, dir 7 oder 8 Posts zu verlinken? Du kannst selbst umblättern, habe ich gehofft. Sorry, wenn ich damit zu viel von dir verlange.

    krümelkacker schrieb:

    Das ist kein Grund so pampig zu werden, meiner Meiung nach.

    Ich sag dir, warum ich so pampig bin. Es geht mir fürchterlich auf die Eier, dass jedes mal, wenn ich irgendwas poste, egal was, irgendetwas kritisiert wird. Noch dazu diesmal zu Unrecht. Ich habe es so verdammt satt. Jedes verdammte Mal.

    Shade Of Mine schrieb:

    Und wenn du nur einen funken intelligenz hättest...

    Wenn du nur ein bisschen Ahnung vom moderieren hättest...

    DocShoe schrieb:

    Bin ich der einzige, den ein (temporärer) pi-Bann nicht stören würde?

    Gute Idee, wäre ich auch dafür. Am besten gleich perma.

    pumuckl schrieb:

    bitte auf den Ton achten, und zwar alle.

    War das nett genug?



  • Ok, um das Thema abzukürzen:
    1. Lesen kann ich tatsächlich schlecht - aber bei mir war ja auch zu lesen, dass ich es nur überflogen hab.
    2. Das Thema hab ich für mich mit QList gelöst, weil auch mein Wochenende nur begrenzt ist. Sollte ich mal in Versuchung kommen, doch eine Liste selbst zu schreiben, werd ich mir den Beitrag gründlichst durchlesen.

    Danke, bitte schließen.



  • 314159265358979 schrieb:

    Ich sag dir, warum ich so pampig bin. Es geht mir fürchterlich auf die Eier, dass jedes mal, wenn ich irgendwas poste, egal was, irgendetwas kritisiert wird. Noch dazu diesmal zu Unrecht. Ich habe es so verdammt satt. Jedes verdammte Mal.

    Ok, dann hör aber auch auf, dasselbe mit Hilfesuchenden zu tun. Antworten im Stil von "der Fehler ist die Verwendung von VCL" sind pure Trollerei, bringen niemandem was, und steigern deine Unbeliebtheit.



  • 314159265358979 schrieb:

    pumuckl schrieb:

    bitte auf den Ton achten, und zwar alle.

    War das nett genug?

    Gemessen am Ton vorher allemal - meiner Meinung nach. Muss aber jeder für sich beantworten, vor allem der Adressat.

    314159265358979 schrieb:

    Ich sag dir, warum ich so pampig bin. Es geht mir fürchterlich auf die Eier, dass jedes mal, wenn ich irgendwas poste, egal was, irgendetwas kritisiert wird. Noch dazu diesmal zu Unrecht. Ich habe es so verdammt satt. Jedes verdammte Mal.

    Henne-Ei-Problem: Was kam zuerst, dein pampiger Ton oder dass dich viele hier auf dem Kieker haben? Und was davon ist leichter zu beheben? Erfahrungsgemäß regt sich die Allgemeinheit hier genauso schnell wieder ab, wie sie sich aufgeregt hat. Gib ihr Gelegenheit dazu und alles ist wieder in Butter.

    Soviel von mir zu dem Thema, mehr werd ich hier nicht schreiben. Denk in Ruhe drüber nach, bitte. Da hier nicht der Platz ist, das auszudiskutieren, und da es vermutlich auch nicht viel Sinn macht da groß drüber zu diskutieren, mach ich den Thread zu. Bei Bedarf bin ich per PN erreichbar (Mail-Funktion im Profil)

    ZU.


Anmelden zum Antworten