[Gelöst] Verstehe diesen Copy Assignment Operator nicht. (simple vector)



  • Bashar schrieb:

    HarteWare schrieb:

    Glaub nicht, dass da was im Buch falsch gemacht wird.

    Wieso nicht? Das ist doch glasklar Quatsch, und das hast du auch erkannt. Anstelle von copy(v) gehört da das Kopieren von v nach p hin.

    naja ich bin halt sehr vorsichtig und such den Fehler erstmal bei mir. Ist schon zu oft vorgekommen, dass ich dachte jemand macht Mist und dabei bin ich selber blöd.

    Da fällt mir grad ein Thread von mir ein, da hab ich mich beschwert, dass der * Operator nicht + macht.



  • Das ist ja OK, aber wenn es nicht um Stilfragen, sondern um logisch begründbares Richtig oder Falsch geht, kann man schonmal das Selbstbewusstsein aufbringen, die Autorität in Frage zu stellen 😉



  • In der Praxis macht man das dann so:

    Vector& Vector::operator=(Vector v) { // Kopie schon bei Argumentübergabe
      std::swap(sz, v.sz);      // oder gleich swap(v);
      std::swap(elem, v.elem);  // und dann eine swap-Funktion selber implementieren
      return *this;
    }
    

    (Copy&Swap-Idiom.)



  • Schreibt man das mit c++11 nicht so?

    class Foo
    {
    public:
        Foo& operator=( const Foo& foo ) = default;
    }
    


  • Ja, die copy() Funktion ist fehlerhaft bzw. funktioniert nur korrekt, wenn beide Vektoren gleich lang sind und kopiert die Daten auch noch in das Array, dass nach dem Funktionsaufruf frei gegeben wird.

    Deine intuitive Lösung hat zwei Probleme:
    - wenn der new Ausdruck eine Ausnahme wirft, bekommst Du das Objekt nicht mehr in einen gültigen Zustand (bestenfalls kannst Du die Vektorlänge auf 0 setzen).
    - Wenn Du einem Vektor sich selbst zuweist, greifst Du beim Kopieren auf bereits frei gegebenen Speicher zu.

    Die einfacher Variante, den Zuweisungsoperator zu implementieren ist folgende:

    Vector& Vector::operator( Vector rhs )
    {
      swap( rhs );
      return *this;
    }
    

    Das setzt dann voraus, dass man ein swap() effektiv und ohne Fehlerquelle implementieren kann:

    void Vector::swap( Vector& other )
    {
      std::swap( elem, other.elem );
      std::swap( sz, other.sz );
    }
    

    Der Copy-c'tor kann werfen, swap nicht. rhs ist eine Kopie, wie die angelegt werden konnte, dann kann swap() nicht mehr fehlschlagen und der Destruktor von temp gibt den ursprünglich allozierten Speicher wieder frei.

    Ich würde das Buch wegwerfen.

    mfg Torsten



  • C++11 schrieb:

    Schreibt man das mit c++11 nicht so?

    class Foo
    {
    public:
        Foo& operator=( const Foo& foo ) = default;
    }
    

    Nein, die default Implementierung funktioniert an der Stelle ja eben nicht. Sie würde nur den Zeiger und den Zähler zuweisen, mit dem Effekt, dass die Adresse des einen Speicherbereichs verloren gegangen ist (memory leak) und auf den anderen Speicherbereich zwei Zeiger zeigen, und der Speicher damit zwei mal freigegeben wird (viel Spaß bei der Fehlersuche).



  • Hallo Torsten,

    bei

    Vector& Vector::operator(Vector rhs)
    

    muss aber dann der Kopierkonstruktor (copy constructor) auch richtig implementiert sein (und nicht der Default genommen werden).
    Nach der "Regel der großen Drei" ist das zwar klar, sollte aber hier nochmals extra erwähnt werden.



  • Vector& Vector::operator=(Vector v) { // Kopie schon bei Argumentübergabe
      std::swap(sz, v.sz);      // oder gleich swap(v);
      std::swap(elem, v.elem);  // und dann eine swap-Funktion selber implementieren
      return *this;
    }
    

    Wird hier denn 'elem' von v nach dem swap automatisch deleted?



  • HarteWare schrieb:

    Wird hier denn 'elem' von v nach dem swap automatisch deleted?

    Das delete sollte im Destruktor stehen und da v am Ende der Funktion "out of scope" geht, wird der Destruktor aufgerufen.



  • Torsten Robitzki schrieb:

    HarteWare schrieb:

    Wird hier denn 'elem' von v nach dem swap automatisch deleted?

    Das delete sollte im Destruktor stehen und da v am Ende der Funktion "out of scope" geht, wird der Destruktor aufgerufen.

    Achja klar, das hatte mir gedanklich gefehlt..


Anmelden zum Antworten