was ist genau der Sinn des Copykonstruktors
-
Moin.
Ich muss mich gerade (3 Tage vor meiner Klausur in c++) mit Klassen auseinaderschlagen und habe ein grundlegendes Problem.
Was macht der Copykonstruktor ?
Wozu brauche ich den ?
Das ist mir trotz des lesens 2er verschiedener Scripte nicht ganz klar geworden.Kann ich eine Klasse nicht einfach mit " = " kopieren ala :
class class1{ }; class1 a , b ; a = b ;
Oder wo genau liegt da der Sinn ??
Gruß Sono
-
Natürlich kannst du zwei Klassen mit = kopieren. Aber wenn du ein anderes Verhalten für diese Kopieroperation definieren willst, als sich der Compiler logisch erschließen kann (Jedes Element einzeln zu kopieren), musst du selbst einen schreiben, der dann aufgerufen wird, wenn du a=b schreibst.
http://www.fh-augsburg.de/informatik/vorlesungen/c_cplus/tutorial/henkel/CopyKonstruktor.html
-
Ich überlade damit quasi den = Operator ?
Ich les mal das Script Thx.
Gruß SOno
-
Noch eine kurze Anmerkung für deine Klausur. Man kopiert keine Klassen, sondern Objekte.
-
moment,
es gibt einen doch nicht ganz unerheblichen Unterschied zwischen
Copy-Konstruktor und Zuweisungsoperator:Kopierkonstruktor:
Der wird immer dann aufgerufen, wenn Objekte kopiert werden sollen.
Dies ist in der Regel dann der Fall, wenn Objekte als Parameter an
Funktionen übergeben werden.
Auch bei der Rückgabe eines Objekts wird der Kopierkonstruktor aufgerufen.einfaches Beispiel:
int summe(int X, int Y) {return X + Y;}
Wenn die Funktion "summe" aufgerufen wird, werden zuerst mal kopien von den
Integern angelegt.Das allerselbe passiert mit selbstgebauten Objekten.
Solange nur bekannte Objekte (also die eingebauten Datentypen wie int, float,
char) usw. verwendet werden, hat der Compiler kein Problem, eine Kopie von einem
Objekt zu erstellen:
Er kopiert einfach alles Bit für Bit vom alten ins neue Objekt.Was aber passiert, wenn z. B. Zeiger in einer Klasse als Membervariablen
vorhanden sind?Genau das allergleiche:
Der Kompiler kopiert Bit für Bit vom alten ins neue Objekt.Dumm gelaufen:
Jetzt haben beide Objekte einen Zeiger auf die selben Daten.Und hier kommt der Kopierkonstruktor ins Spiel:
er wird, falls vorhanden genau hier aufgerufen.
Somit hast du die Möglichkeit, selbst zu entscheiden, wie kopiert wird.
Normalerweise wird jetzt für das neue Objekt auch neuer Speicher für
die Daten zugewiesen und die Daten werden vom alten ins neue Objekt reinkopiert.Somit sind beide Objekte auch wirklich eigenständig.
Zuweisungsoperator:
Hier verhält es sich ganz ähnlich.
mitObj1 = Obj2;
wird standardmäßig alles Bit für Bit von Obj2 nach Obj1 kopiert.
Mit dem selben Problem:
Bei Zeigern innerhalb eines Objekts:
Zwei Objekte zeigen auf den selben Speicher.Hier den Zuweisungsoperator überladen, und alles ist in Butter.
[edit]viel zu spät[/edit]
-
Ich überlade damit quasi den = Operator ?
zuweisungsoperator und copykonstruktor sind unterschiedlich:
A a(123); A b(a); //nur hier wird der cctor verwendet a = b; //hier kommt operator= dran.
edit: auch ich war zu spät
-
Ich weiß , aber danke für den Hinweis .
Wenn ich mich so doof in der Klausur ausdrücken würde dann hätte ich ein Problem.
Sollte ich mir noch abgewöhnen.Ps. Danke an die Zu-Spät-Kommer. Jetzt habe ich es begriffen. Das war genau das was mir zum Verständnis gefehlt hat .
Echt kein Witz auf einmal verstehe ich was der Seit 10 Seiten in dem Script von mir will .
Gruß Sono
-
anonymus schrieb:
Solange nur bekannte Objekte (also die eingebauten Datentypen wie int, float,
char) usw. verwendet werden, hat der Compiler kein Problem, eine Kopie von einem
Objekt zu erstellen:
Er kopiert einfach alles Bit für Bit vom alten ins neue Objekt.Was aber passiert, wenn z. B. Zeiger in einer Klasse als Membervariablen
vorhanden sind?Genau das allergleiche:
Der Kompiler kopiert Bit für Bit vom alten ins neue Objekt.Dumm gelaufen:
Jetzt haben beide Objekte einen Zeiger auf die selben Daten.Und hier kommt der Kopierkonstruktor ins Spiel:
er wird, falls vorhanden genau hier aufgerufen.
Somit hast du die Möglichkeit, selbst zu entscheiden, wie kopiert wird.
Normalerweise wird jetzt für das neue Objekt auch neuer Speicher für
die Daten zugewiesen und die Daten werden vom alten ins neue Objekt reinkopiert.Somit sind beide Objekte auch wirklich eigenständig.
Das sind dann Shallow Copy und Deep Copy wenn ich das richtig verstanden habe.
-
-
Man sollte noch etwas genauer zwischen Copy-Konsturktor und operator= unterscheiden:
Der Copykonstruktor legt ein Völlig neues Objekt an und initialisiert dessen Membervariablen, ändert evtl. danach noch die eine oder andere.
Der operator= ist eine normale Methode und kann daher nur für bereits initialisierte Objekte aufgerufen werden. Der copy-konstruktor ist daher im Grunde schneller, wenn man ein neues Objekt erzeugen will, da für den operator= erst ein anderer Konstruktor aufgerufen werden müsste, der nur Zeit frisst.
Der Copy-konstruktor und der operator= werden im Übrigen vom Compiler selbst erzeugt, wenn sie nicht definiert wurden und das Programm irgendwo implizit oder explizit einen Kopiervorgang verlangt. Zum Beispiel werden bei Funktionen, deren Parameter per Wert übergeben werden, diese Parameter kopiert, anders als bei der Parameterübergabe per Referenz.
Wenn man also nichttriviale Klassen schreibt, sollte man sich immer Gedanken über copy-Ctor und operator= machen. Wenn bitweises Kopieren genügt, überlässt man die arbeit dem Compiler und macht an entsprechender Stelle im header evtl. ne kleine Notiz. Genügt das nicht, dann muss man die beiden entweder selbst definieren (wenns ne sinnvolle Umsetzung gibt) oder aber als private deklarieren und nicht definieren, um ihren gebrauch zu verhindern.
-
Wenn bitweises Kopieren genügt, überlässt man die arbeit dem Compiler und macht an entsprechender Stelle im header evtl. ne kleine Notiz
Da der Standard-Copy-Ctor keine bitweise Kopie erzeugt ist dieser Hinweis irreführend. Richtig wäre: wenn eine Member-weise Kopie korrekt ist, reicht der Standard-Copy-Ctor.
Er kopiert einfach alles Bit für Bit vom alten ins neue Objekt.
Nope. Er kopiert Member-für-Member.
Hier verhält es sich ganz ähnlich.
mitObj1 = Obj2;
wird standardmäßig alles Bit für Bit von Obj2 nach Obj1 kopiert
Nope. Hier wird Member-für-Member zugewiesen.
Bitweise werden POD-Typen kopiert. Alle anderen werden per Copy-Ctor kopiert.
Analoges gilt für den operator=.
-
Mir fällt gerade auf, dass ich natürlich voreilig Unsinn geschrieben habe. Im a=b-Fall bei 2 initialisierten Objekten wird natürlich nicht der Kopierkonstruktor aufgerufen, weil beide Objekte ja schon konstruiert sind. Aber im Beispiel von Mr. Volkard ist ja plausibel dargelegt, wieso es notwendig sein kann, einen eigenen Kopierkonstruktor zu definieren.
class1 a , b ; a = b ; // Zuweisungsoperator
class1 a; class1 b(a) // Kopierkonstruktor (b wird mit a als Vorlage erstellt);
class1 a; void machwas(class1 arg) {} int main() { machwas(a); // Ebenfalls Kopierkonstruktor zur Parameterübergabe }
-
HumeSikkins schrieb:
Er kopiert einfach alles Bit für Bit vom alten ins neue Objekt.
Nope. Er kopiert Member-für-Member.
char * p1 = ...; char * p2; p2 = p1;
hm, ok du chef, ich nix,
aber wo ist der Unterschied zwischen "p2 wird p1 zugewiesen" und
"p1 wird Bit für Bit nach p2 kopiert"
(bis auf das, dass natürlich nicht jedes Bit einzeln kopiert wird, sondern
beim 32 Bit Prozi 32 Bit gleichzeitig)Ergebnis ist doch das gleiche?
-
@anonymus
Mir scheint du hast meinen Beitrag nicht verstanden. Der automatisch generierte Copy-Ctor kopiert Member-Für-Member. POD-Typen werden dabei bitweise kopiert. Alle anderen wiederum durch aufruf ihres Copy-Ctors.In dem von dir geposteten Code wird weder ein Copy-Ctor generiert noch einer aufgerufen. Dort wird in der Tat nur die Adresse kopiert, so dass p2 nachher auf das selbe zeigt wie p1.
Ergebnis ist doch das gleiche?
Nein ist es nicht.
struct X { std::string s; }; ... X x1; X x2(x1);
Würde hier, wie behauptet, bitweise kopiert werden, würde dies zu unendlich viel Schmerz führen. Da aber nicht bitweise kopiert wird, gibt es keinen Schmerz und man muss für X auch keinen Copy-Ctor erstellen.
-
ok,
bin überzeugtdanke
-
Ich weiß nicht ob das schon einer geschrieben hat aber bei der Initialisierung eines Objekts wir auch der Kopierkonstruktor aufgerufen...
MyClass a; MyClass b = a;
-
ja, da schon, aber das ist kein anderer fall als
Maclass b(a);
nur ne andre schreibweise
//edit
boah hume hat 9999 beiträge
-
Noch ein Post mehr und er bekommt 'nen Keks.