Wieder der Copy-Konstruktor



  • 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.xyz

    Etwas 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.



  • @Simon2
    Ist ja letztlich irrelevant, da eine Signatur wie:

    Foo(Foo f);
    

    schlicht nicht erlaubt ist.



  • HumeSikkins schrieb:

    @Simon2
    Ist ja letztlich irrelevant, da eine Signatur wie:

    Foo(Foo f);
    

    schlicht nicht erlaubt ist.

    Aber ich finde es immer besser, wenn ich einen konkreten Grund sehe, warum etwas nicht erlaubt ist. Kann ich mir einfach leichter merken, wenn es plausibel ist.

    Gruß,

    Simon2.


Anmelden zum Antworten