Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » kopierkonstruktor zusammenhang Zuweisungsoperator

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
28.06.2003, 15:48 Uhr
~VesaMan
Gast


Man benötigt einen Kopierkonstruktor doch um eine Kopie eines Objekts einer Klasse zu erstellen. Gibt es noch andere Dinge wozu man einen Kopierkonstruktor braucht?

Welcher Zusammenhang besteht dann mit dem Zuweisungsoperator?
heißt das, wenn ich dann zum beipiel im hauptprogramm:

C++:
(objekt) v =w;


eingebe, dass von w eine kopie erstellt wird mit dem kopierkonstruktor und dann an v zugewiesen wird?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
28.06.2003, 20:23 Uhr
virtual
Sexiest Bit alive
(Operator)


Ein Copyconstructor dient dazu, eine Kopie neu zu konstruieren. Ein zuweisungsoperator wird dann verwendet, wenn man einer bestehenden Instanz etwas zuweisen will.

C++:
string hallo("Welf");
string kopie(hallo); // Copy constructor;

hallo = kopie; // Zuweisungsoperator


Nun könnte man etwas vorschnell sagen: Sobald da irgendwie ein "=" Zeichen auftaucht, dann ist der Zuweisungoperator gefragt. Dem ist nicht so:

C++:
string hallo("Welf");
string kopie = hallo; // Auch Copy constructor;


Wenn eine Variable deklariert und initialisiert wird, dann wird für die initialisierung auch der Constructor aufgerufen. (und nicht, wie man annehmen koennte zunächst der Defaultconstructor und danach der Zuweisungsoperator).

Standardmäßig bringt jede Klasse einen Copyconstructor und einen Zuweisungsoperator mit. Diese Standardversionen machen allerdings nur eine Bitweise kopie von Quelle nach Ziel. So kann so eine Klasse hier ohne expliziten CopyConstructor/Zuweisungoperator auskommen:

C++:
class Vector3D
{
    int x;
    int y;
    int z;
...
};


Anders sieht es aus, wenn man eine tiefe Kopie benötigt. Nehmen wir mal als Beispiel eine Klasse String:

C++:
class String
{
private:
    char* text;
    int laenge;
public:
    String(const char* text)
    {
        this->laenge = strlen(text);
        this->text = new[this->laenge+1];
        strcpy(this->text, text);
    }
    virtual ~String()
    {
        delete [] text;
    }
};


Mit dieser Klasse koennte man nun - ohne das Der Compiler meckert - schreiben:

C++:
String a("Hallo");
String b(a); // Copy constructor


Es gibt ja diesen Standard copy-constructor, der eine Bitweise Kopie macht. Dummerweise Wird das Programm aber mit an Sicherheit grenzender Wahrscheinlichkeit abstürzen.
Der Grund ist, daß ja irgendwann der Destructor von a und b aufgerufen wird und beide werden dann versuchen, den gleichen Speicherbereich freizugeben. Möglichweise wird man schon davor bemerkt haben, daß Änderungen an a auch plötzlich in b sichtbar werden. Bei unserer Klasse String muß dahr der CopyConstructor und der Zuweisungsoperator dafür sorgen, daß jedes Strignobjekt seinen eigenen Text haben, in dem sie ihren Karm machen.
Also zB:

C++:
class String
{
    ...
    String(const String& quelle) // Copy-Constructor
    {
       this->laenge = quelle->laenge;
       this->text = new char[this->laenge];
       strcpy(this->text, quelle->text);
    }
    String& operator = (const String& quelle) // Zuweisungsoperator
    {
        delete [] this->text;
       this->laenge = quelle->laenge;
       this->text = new char[this->laenge];
       strcpy(this->text, quelle->text);
       return *this;
    }
};


Die große Ähnlichkeit der Implementierung von Zuweisungsoperator und Copyconstructor sollte aber jetzt nicht dazuverleiten, einfach sowas zu machen (Mircosoft tut es in CString ):

C++:
class String
{
    ...
    String(const String& quelle) // Copy-Constructor
    {
       this->text = NULL;
       this->operator = (quelle);
    }
    String& operator = (const String& quelle) // Zuweisungsoperator
    {
        delete [] this->text;
        this->laenge = quelle->laenge;
        this->text = new char[this->laenge];
        strcpy(this->text, quelle->text);
        return *this;
    }
};  


Damit verbaut man sich die Möglichkeit, exceptionsicheren Code zu schreiben. Im Sinne der Exceptionsicherheit kann es sinnvoll sein, es genau umgekehrt zu machen:
Da ein new[] jederzeit schiefgehen kann, hat obige Implementierung des Zuweisungsoperator den nachteil, daß der Zuweisungsoperator ggf. ein Ungültiges Objekt hinterläßt:

C++:
class String
{
    String& operator = (const String& quelle) // Zuweisungsoperator
    {
        delete [] this->text;
        this->laenge = quelle->laenge;
        this->text = new char[this->laenge]; // WEnn dies schief geht, wird eine bas_alloc exception geworfen
        strcpy(this->text, quelle->text);
        return *this;
    }
};


Wir haben bereits mit delete[] den Speicher freigegeben und wenn das new[] schief geht, dann stehen wir im Regen. weil this->text auf nicht mehr gültigen Speicherbereich verweist.
Um exceptionsichere Zuweisungsoperatoren zu schreiben bedient man sich ganz gerne einer Swap-methode (die die Inhalte der eigenen Instanz mit der einer anderen tauscht) und des Copyconstructors:

C++:
class String
{
   void swap(String& other)
   {
       std::swap(other->text, this->text);
       std::swap(other->laenge, this->laenge);
   }
   String& operator = (String& quelle)
   {
       String temp(quell); // Copyconstructor. Kann zwar eine Exception werfen, tut aber nicht weh
       swap(temp); // Unseren Inhalt mit dem vom Temp vertauschen
       return *this; // temp wird nun gelöscht, damit auch unserer alter Inhalt.
   }
};


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 28.06.2003 um 20:30 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
28.06.2003, 20:31 Uhr
VesaMan



ah ok, vielen dank für die ausfühliche antwort
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: