Wieder der Copy-Konstruktor
-
naja, const sagt an dieser stelle nur "ich verändere das übergebene objekt nicht"
C& das ist nicht der adressoperator sondern der reference operator. also das objekt wird als reference übergeben und nicht als kopie..sagt dir call by reference und call by value etwas?
und naja die varibale bestimmt ja nur den namen des übergebenen objekts
-
muhi schrieb:
Ja nur in dem Beispiel aus dem ich diesen Codeschnipsel kopiert habe, wird auch kein neuer Speicher allokiert....
Ich weiß jetzt nicht, welche "Speicherallokation" Du meinst.
Wenn Du aber meinst, ein CopyCtor sollte Speicher für das Objekt selbst (hier also "ein C") allokieren: Braucht er nicht !! Der CpyCtor wird erst aufgerufen, wenn der Speicher für ein neues Objekt bereits allokiert wurde !
Es wird auch nicht der CpyCtor des "alten", sondern der des "neue Objektes" aufgerufen.class C { int i; public: C() : i(0) {} C(C const& c) : i(c.i) { c.i = 2; // ---> FEHLER !!! geht nicht wegen "const" } void seti(int a) {i = a; } }; int main() { C c1; // c1.i == 0 c1.seti(1); // c1.i == 1 C c2(c); // allokiert erst Speicher für c2 und // ruft dann (implizit) c2.C(c1); (== CpyCtor) auf // => c2.i == 1 ...Wenn C jetzt "Heapspeicher" für seine Variablen braucht (sprich: "irgendwo ein new/delete macht)), muß das wahrscheinlich im CpyCtor auch passieren.
muhi schrieb:
K das einzige was ich noch wissen will, wieso hier der Adress-Operator "&" in der Argumentliste steht....
Naja, wenn da kein "&" stände, würde der Compiler eine weitere ("temporäre") Kopie von c1 anlegen, um die dann dem CpyCtor von c2 zu übergeben. Das wäre einerseits unnötig/zeitraubend und andererseits sehe ich da irgendwie "rekursive Probleme" beim CpyCtor (muß ich mal ausprobieren) (schließlich wird das temporäre Objekt ja selbst auch wieder per CpyCtor erzeugt, für desse n Aufruf ja eine andere Temporäre Kopie erzeugt werden muß, für die der CpyCtor aufgerufen wird, für ....)
Gruß,
Simon2.
-
Sowas war gemeint:
class foo { private: int *xyz; public: foo() : xyz( new int( 10 ) ) {} ~foo() { delete xyz; } void set( int num ) { *xyz = num; } int get() const { return *xyz; } }; int main() { foo bar; bar.set( 50 ); foo foobar( bar ); foobar.set( 70 ); std::cout << bar.get() << " " << foobar.get(); // Ausgabe 70 70 } // Fehler beim zerstören von foobarDie Lösung ist also ein Copy C'tor der auch xyz korrekt kopiert.
foo( const foo &other ) { // selbstzuweisung testen, etc... xyz = new int( *other.xyz ); }Dann passts.
grüße
-
foo( const foo &other ) { // selbstzuweisung testen, etc... xyz = new int( *other.xyz ); }dazu hab ich auch ne kleine kurze Frage. Den Stern bei *other.xyz muss man setzen, weil xyz ein Zeiger ist, richtig?
Weil other ist ja eine Referenz, da braucht man die Dereferenzierung ja nicht. Also wegen xyz oder?
Und was wäre, wenn man den Stern weglassen würde? Wurde man dann mit der Adresse von xyz arbeiten?
-
Ok ich versteh gar nix mehr ich glaub ich gebs auf...
-
deetee schrieb:
foo( const foo &other ) { // selbstzuweisung testen, etc... xyz = new int( *other.xyz ); }dazu hab ich auch ne kleine kurze Frage. Den Stern bei *other.xyz muss man setzen, weil xyz ein Zeiger ist, richtig?
Weil other ist ja eine Referenz, da braucht man die Dereferenzierung ja nicht. Also wegen xyz oder?
Und was wäre, wenn man den Stern weglassen würde? Wurde man dann mit der Adresse von xyz arbeiten?
So isses!
muhi schrieb:
Ok ich versteh gar nix mehr ich glaub ich gebs auf...
Was verstehst du denn nicht?
grüße
-
muhi schrieb:
Ok ich versteh gar nix mehr ich glaub ich gebs auf...
Ist gar nicht so schwer:
- Was ist "other" ? Richtig: "const foo &" = eine (const-)Referenz; d.h. man kann auf other genauso zugreifen wie auf ein "normales Objekt": other.xyz.
- Was ist xyz ? Richitg: Ein "int* " = ein Zeiger; d.h. man greift auf den Speicherplatz, auf den er zeigt mit * oder -> zu: *xyz = 3
- Wie greift man auf xyz von other zu ? Richtig: other.xyz
- Wie greift man auf den Speicherplatz, auf den other.xyz verweist zu ? Richtig: *(other.xyz) oder (wenn man die Operatorenreihenfolge beachtet - man braucht keine Klammern) *other.xyzEtwas verwirrend wirkt wahrscheinlich, weil es so aussieht, als bezöge sich * auf other (sowas wie other) ... tut's aber nicht

Es bezieht sich auch xyz; so in der Art "_____.xyz".Gruß,
Simon2.
-
Worauf ist bei X(X& c) die Referenz gereichtet?
Wies funzt hier denn kein call by value?
-
c ist eine reference auf das übergebene objekt oder auch ein anderer name für das übergebene objekt. du arbeitest also direkt mit dem übergebenem objekt vom typ X
-
Moment mal, das heisst es ist zwingend dass alle Objekte die durch den Copycon erzeugt werden eine Ref auf das ursprungsobjekt ist?
-
eh nun verwirrst du mich etwas.
also ein CopyCon kopiert das übergebene objekt und man hat am ende dann zwei objekte. das zu kopierende und einmal die kopie.
sie sind damit von einander unabhängig und wenn du das eine löschst ist das andere noch vorhanden.
-
Im CTor sitzt Du im inneren des Kopiergerätest und das übergebene Objekt ist das Baltt , welches oben auf der Glasblatte liegt und kopiert werden möchte

-
class A{ public: A(): i( new int(1)); ~A(); setI( int in){ *i = in; } private: int *i; }; A::~A(){ delete i; } // so könnte dann der copyconst vom compiler genereiert aussehen A::A( const A& src){ i = src.i; //kopiert also den zeiger //this.i und src.i zeigen also nun auf den gleichen //speicherbereiche ( flache kopie ) } /////////////////////////// //mit geschriebenem copyconst class B{ public: B():i( new int(1)); ~B(); B(const B& src ); setI( int in){ *i = in; } private: int *i; }; B::~B(){ delte i; } B::B(const B& src){ if( this != &src ){ //überprüfen ob zuweisung an sich selbst i = new Int(1); //neuen speicher alloziieren *i = *(src.i); //kopiere den wert //src.i und this.i zeigen auf unterschiedlichen speicher //tiefe kopie } }das wäre dann nen prog:
int main{ A* a1 = new A(); a1->setI(234); A *a2( a1 ); a2->setI( 9876 ); // nun ist auch *(a1.i) == 9876 delete a1; a2->setI( 21 ); // error der pointer von i zeigt nämlich nun in nicht //alloziierten speicher, der wurde nämlich mit dem zerstören von a1 wieder //freigegeben B * b1 = new B(); b1->setI( 45 ); B *b2 = new B(b1); b2->setI( 565 ); // *(b1.i) ist immer noch 45 delete b1; b2->setI(45677); //geht ohne weiteres. der pointer ist immer noch ok, da er auf //seinen eigenen speicherbereiche zeigt return 0; }so ich hoffe das hilft
-
aso ja stimmt sry, trotzdem wieso funzt hier kein normales call by value??
EDIT: is keine antwort auf vorposter hab gar nur zu spät gepostet-
-
wenn ich mich nicht täusche MUSS der CopyConst diese Signatur haben.
Klasse::Klasse( const Klasse& src){}
dabei ist src natürlich nur ein bezeichner und kann auch anders lauten
wäre es nämlich keine reference sondern ein call by value würdest du das objekt erstmal beim übergeben kopieren und dann nochmals innerhalb deines kopierkonstruktors.
nun stelle dir mal eine super komplexe klasse vor die mehr als 10000 andere objekt enthält die wiederum etwas komplexer sind.
und nun male dir mal aus weöche performance auswirkungen es hätte jedesmal alle objekte 2 mal zu kopieren...
-
ConfusedGuy schrieb:
wenn ich mich nicht täusche MUSS der CopyConst diese Signatur haben.
Klasse::Klasse( const Klasse& src){}
Du täuschst dich. Korrekt ist, dass der Copy-Ctor einen Referenz-Parameter erhalten muss. Dabei ist aber egal, ob das Ziel der Referenz als const, volatile, const volatile oder nichts von alledem angesehen werden soll.
wäre es nämlich keine reference sondern ein call by value würdest du das objekt erstmal beim übergeben kopieren und dann nochmals innerhalb deines kopierkonstruktors.
[...]
und nun male dir mal aus weöche performance auswirkungen es hätte jedesmal alle objekte 2 mal zu kopieren...Es käme noch viel schlimmer, da du nicht zweimal sondern bis in alle Ewigkeit kopieren würdest. Beim "by value"-Aufruf wird eine Kopie erzeugt. Für das Erzeugen einer Kopie wird der Copy-Ctor verwendet. Würde der Copy-Ctor seinen Parameter "by value" übernehmen, müsste beim Aufruf des Copy-Ctors erstmal wieder eine Kopie erzeugt werden. Das würde wieder den Copy-Ctor aufrufen, wobei wieder eine Kopie erzeugt werden müsset, was wieder den Copy-Ctor aufrufen würde... und so weiter ...
-
ah gut, dann habe ich ja auch noch was gelernt

danke
-
und ich auch. danke.

-
HumeSikkins schrieb:
...
Es käme noch viel schlimmer, da du nicht zweimal sondern bis in alle Ewigkeit kopieren würdest....Schön, habe ich also recht vermutet. (Habe ich aber noch nirgendwo gelesen ... sollte man vielleicht mal aufschreiben).
Gruß,
Simon2.
-