Shallow Copy



  • Hallo,

    kurze Frage: Ist der default copy constructor ausreichend, wenn ich char* Attribute in einer Klasse habe, oder muss ich dafür einen extra copy constructor schreiben (siehe Beispiel)? Danke schon mal für die Antwort.

    class X
    {
      public:
        X(char* s) : str(s) {};
        virtual ~X() {};
        // ... weitere Methoden ...
      private:
        char* str;
    }
    


  • Das kommt ganz darauf an, wie du diese char* verwenden willst. Wenn alle Kopien eines Objekts den selben Speicher verwenden sollen, reicht der Standard-Copy-Ctor. Aber normalerweise benötigt man einen eigenen Copy-Ctor dafür:

    class X
    {
    public:
      X(int size):str(new char[size]),len(size) {}
      X(const X& other):str(new char[other.len]),len(other.len)
      {
        strcpy(str,other.str);
      }
      ~X() {delete[] str;}
    private:
      char* str;
      int len;
    };
    

    (und am besten spendierst du der Klasse auch noch einen Zuweisungsoperator, um ganz sicher zu gehen)



  • Wenn mit den String-Zeigern sonst nichts gemacht wird reicht das so. Wenn im Default Dtor (oder irgendwo im Kontext der im Beispiel nicht zu erkennen ist) allerdings Speicher der char* freigegeben würde, müsste bei Zuweisung/Kopie auch entsprechendes geschehen.

    Oder nimm std::string um auf der sicheren Seite zu sein:

    class X
    {
      public:
        X(const std::string& s) : str(s) {}
        virtual ~X() {}
        // ... weitere Methoden ...
      private:
        std::string str;
    };
    


  • Hm auch wenn ich nicht genau weiß was eine Shallow copy genau sein soll..
    In dem Fall, dass du unabhängig von der anderen Instanz sein willst musst du auf jeden Fall einen cctor selber machen. Also Speicher holen und den string kopieren. Ich würde sowieso std::string verwenden, dann hast du das Problem nicht mehr.



  • @templäd:

    Ne Shallow Copy hast i.A., wenn nur ein Zeiger kopiert wird. Das Gegenteil kopiert eben die Inhalte aller Zeiger und heisst üblicherweise Deep Copy.



  • Shallow copy kommt dann wohl eher aus der Welt mit standardmäßig referenzgezählten Zeigern. Da mir in c++ nicht so viele Anwendungsfälle begegnet sind.



  • templäd schrieb:

    Shallow copy kommt dann wohl eher aus der Welt mit standardmäßig referenzgezählten Zeigern.

    Shallow copy ist vor allem das, was dir der Compiler von sich aus bereitstellt, wenn du keine eigenen Methoden für die Kopie schreibst.



  • IMHO ist die Kopie jeder bessere String-Klasse eine Shallow-Copy mit Copy-On-Write. Jedenfalls gibts das für QT, MFC und sicherlich auch STL (oder?)...



  • LordJaxom schrieb:

    IMHO ist die Kopie jeder bessere String-Klasse eine Shallow-Copy mit Copy-On-Write. Jedenfalls gibts das für QT, MFC und sicherlich auch STL (oder?)...

    Copy-On-Write für Strings ist ein ganz gewaltiger Krampf. Wenn man sich die Entwicklung jener in der STL angeschaut hat, um eine referenzgezählte Implementation zu ermöglichen, dann weiß man, welches Ungeheuer man sich einbrockt, falls man die selbst implementieren will.

    Mal ein ganz simples Beispiel:

    std::string s1 = "hallo";
    char& c = s1[0];
    std::string s2 = s1; /// Es MUSS kopiert werden, da eine Referenz auf s1 bestehen könnte. s1 kann hier garnicht invalidiert werden, da er im Konstruktor konstant ist
    c = 'H'; // wir wollen ja schließlich nicht, dass s2 geändert wird
    

    Hebelt das nicht schon fast alle Fälle für COW aus? Konstante Strings wären eine Ausnahme, aber das war's. Außerdem ist das ständige Referenzgezähle im Multithreading-Einsatz der absolute Overkill. Von "besser" kann da nicht so wirklich die Rede sein 🙂


Anmelden zum Antworten