frage zum kopierkonstruktor



  • ich habe mal einen neuen thread aufgemacht weil sich der letzte in eine andere richtung entwickelte... .
    also mir ist aufgefallen, dass wenn ich den kopierkontruktor entferne, ich keine referenz beim aufruf von bsp.-weise:

    vektor &mult(vektor v);
    

    brauche... .
    also

    vektor mult(vektor v);
    

    und dass programm trotzdem kompilliert wird und funktioniert.
    Caipi hatte das anhand eines temporären objektes erklärt an das man keine refernz heften kann.
    nun zur frage: in wie fern unterscheidet sich eigentlich der vom system erzeugte c-ctr von meinem eigenen, denn der vom system braucht keine refernz. und warum muss man dem selbst erzeugten eine referenz geben, dass scheint cheint ja vom standard festgelegt worden zu sein?!
    UND: wenn ich mir c-ctr einen gebastelt habe, und ich dementsprechend eine refernz-fkt. baue (weil sonst der compiler meckert...) verstehe ich immer noch nicht so ganz warum bei diesen rechenfkt. der so "schlimme" c-ctr. aufgerufen wird 😞
    ich dachte "früher" (bis gestern) dass dieser explizit NUR bei

    vektor v(/*vektor*/ foo);
    

    aufgerufen wird. warum bei

    a.mult(2).sub(c.mult(2)).add(d.mult(2))
    

    😕

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    class vektor
    {
          private:
                  float *v;
    
                  float x;
                  float y;
                  float z;
    
          public:
                 vektor();
                 //vektor(vektor &ref);
    
                 vektor(float);
                 vektor(float, float);
                 vektor(float, float, float);
    
                 void definiere(float, float, float);
                 void ausgabe();
                 float* get_vektor();
    
                 /*rechnen*/
                 vektor &mult(vektor v);
                 vektor &div(vektor v);
                 vektor &add(vektor v);
                 vektor &sub(vektor v);
    
                 vektor &mult(float t);
                 vektor &div(float t);
                 vektor &add(float t);
                 vektor &sub(float t);
    };
    
    vektor mult(vektor &v, vektor &v2);
    vektor div(vektor &v, vektor &v2);
    vektor add(vektor &v, vektor &v2);
    vektor sub(vektor &v, vektor &v2);
    
    vektor mult(vektor &v, float t);
    vektor div(vektor &v, float t);
    vektor add(vektor &v, float t);
    vektor sub(vektor &v, float t);
    
    vektor::vektor() : x(0), y(0), z(0) {};
    //vektor::vektor(vektor &ref) : x(ref.x), y(ref.y), z(ref.z) {};
    vektor::vektor(float rx) : x(rx), y(0), z(0) {};
    vektor::vektor(float rx, float ry) : x(rx), y(ry), z(0) {};
    vektor::vektor(float rx, float ry, float rz) : x(rx), y(ry), z(rz) {};
    
    void vektor::definiere(float rx, float ry, float rz)
    {
         x = rx;
         y = ry;
         z = rz;
    }
    
    void vektor::ausgabe()
    {
         cout<<"X: "<<x<<endl;
         cout<<"Y: "<<y<<endl;
         cout<<"Z: "<<z<<endl;
    }
    
    float* vektor::get_vektor()
    {
           v = new float[3+1];
           v[0] = x;
           v[1] = y;
           v[2] = z;
           v[3] = 4; //groeße
           return v;
           delete [] v;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    vektor &vektor::mult(vektor v)
    {
         x *= v.x;
         y *= v.y;
         z *= v.z;
         return *this;
    }
    vektor &vektor::mult(float t)
    {
         x *= t;
         y *= t;
         z *= t;
         return *this;
    }
    vektor mult(vektor &v, vektor &v2)
    {
           vektor v_r = v;
           v_r.mult(v2);
           return v_r;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    vektor &vektor::div(vektor v)
    {
         x /= v.x;
         y /= v.y;
         z /= v.z;
         return *this;
    }
    vektor &vektor::div(float t)
    {
         x /= t;
         y /= t;
         z /= t;
         return *this;
    }
    vektor div(vektor &v, vektor &v2)
    {
           vektor v_r = v;
           v_r.div(v2);
           return v_r;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    vektor &vektor::add(vektor v)
    {
         x += v.x;
         y += v.y;
         z += v.z;
         return *this;
    }
    vektor &vektor::add(float t)
    {
         x += t;
         y += t;
         z += t;
         return *this;
    }
    vektor add(vektor &v, vektor &v2)
    {
           vektor v_r = v;
           v_r.add(v2);
           return v_r;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    vektor &vektor::sub(vektor v)
    {
         x -= v.x;
         y -= v.y;
         z -= v.z;
         return *this;
    }
    vektor &vektor::sub(float t)
    {
         x -= t;
         y -= t;
         z -= t;
         return *this;
    }
    vektor sub(vektor &v, vektor &v2)
    {
           vektor v_r = v;
           v_r.sub(v2);
           return v_r;
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    int main(int argc, char *argv[])
    {
        vektor temp;
        vektor a(4,1);
        vektor b(-2,-1);
        vektor c(-2,2);
        vektor d(1,-3);
    
        temp = a.mult(2).sub(c.mult(2)).add(d.mult(2));
        temp.ausgabe();
    
        return EXIT_SUCCESS;
    }
    


  • exigoner schrieb:

    float* vektor::get_vektor()
    {
           v = new float[3+1];
           v[0] = x;
           v[1] = y;
           v[2] = z;
           v[3] = 4; //groeße
           return v;
           delete [] v;
    }
    

    😮 😮 😮



  • Ich habe zwar den anderen Beitrag nic gelesen aber egal 😛

    in wie fern unterscheidet sich eigentlich der vom system erzeugte c-ctr. und warum muss man dem selbst erzeugten eine referenz geben, dass scheint cheint ja vom stan**** festgelegt worden zu sein?!

    Der vom Compiler erzeuge cc'tor macht eine 1zu1 kopie von deiner Klasse, also:

    member = a.member;
    sinn = a.sinn;
    usw.
    

    Wenn du aber deinen eigenen cc'tor schreibst kannst du dieses Verhalten einschränken...

    Stell dir vor du hättest einen Zeiger der auf einen Bereich in deinem Speicher zeigt.
    Bei den cc'tor vom Compiler würde ja dann alles jenem zugewiesen und somit würde der Zeiger der neunen Klasse auf den selben Bereich der anderen Klasse zeigen.
    Das wäre dann schlecht weil ne änderung an einer Klasse auch die daten der anderen Klasse ändern würde.

    Vom zerstören einer Klasse wollen wir erst gar nicht mal reden 😃

    Nun zu den referenzen im cc'tor.

    vektor (vektor v);
    

    Sagen wir du machst dann so:

    vektor a;
    ...
    vektor b(a);
    

    Jetzt wird ja der cctor aufgerufen. Aber um dann im cctor v zu erzeugen muss ja auch sowas passieren:

    v(a);
    

    Also wieder ein cctor und dann wieder und immer so weiter. Er kommt nie in den cctor rein weil er immer einen neuen erzeugt, weil du ja das objekt via wert übergibst...
    Machst du es aber so:

    vektor (vektor &v);
    

    Wird es per referenz übergeben und alles ist dann schön und gut außer das dann v im cctor sich auch das objekt im main bezieht, also folglich änderbar ist, deswegen:

    vektor (const vektor &v);
    

    😃 😃 😃



  • ssm schrieb:

    exigoner schrieb:

    float* vektor::get_vektor()
    {
           v = new float[3+1];
           v[0] = x;
           v[1] = y;
           v[2] = z;
           v[3] = 4; //groeße
           return v;
           delete [] v;
    }
    

    😮 😮 😮

    funzt, es etwa nicht? ich war nur zu faul einen destruktor zu schreiben...

    Freak_Coder schrieb:

    Also wieder ein cctor und dann wieder und immer so weiter. Er kommt nie in den cctor rein weil er immer einen neuen erzeugt, weil du ja das objekt via wert übergibst...

    wusst ich nicht 🙂 ich dachte das bei der wertübergabe eine kopie erzeugt wird und diese dann bearbeitet wird. das objekt das die dten kopiert bekommen soll bekommt diese dann praktisch von der kopie des zu kopierenden objektes 😃 so meine theorie [MIST]

    nja zu den oberen fragen die ich hatte:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-120378.html

    exigoner schrieb:

    ...
    UND: wenn ich mir einen c-ctr gebastelt habe, und ich dementsprechend eine refernz-fkt. baue/brauche (weil sonst der compiler meckert...) verstehe ich immer noch nicht so ganz warum bei diesen rechenfkt. der so "schlimme" c-ctr. aufgerufen wird 😞
    ich dachte "früher" (bis gestern) dass dieser explizit NUR bei

    vektor v(/*vektor*/ foo);
    

    aufgerufen wird. warum bei

    a.mult(2).sub(c.mult(2)).add(d.mult(2))
    

    😕

    das problem war, dass ich immer einen fehler bekam wenn ich keine entsprechende refernzfkt. hatte (vektor mult(vektor v);), weil der c-ctr. bei mir auch eine refernz hatte-->is ja immer so(siehe link), also musste aus irgend einem grund der c-ctr. bei der fkt. aufgerufen wurden sein. WARUM?



  • Das ist nicht Dein Ernst, oder?

    float* vektor::get_vektor()
    {
           v = new float[3+1];
           v[0] = x;
           v[1] = y;
           v[2] = z;
           v[3] = 4; //groeße
           return v;
           delete [] v;
    }
    

    Du musst Dich schon entscheiden, ob Du die Funktion beenden willst, oder nicht.

    BTW, Du darfst den Speicher nicht wieder freigeben (egal wie Du die Funktion umstellst). Der Aufrufer bekommt sonst arge Probleme.

    Noch ein BTW, die Größe als letztes Element. Wie bitte willst Du das nutzen? Woher weisst Du was das letzte Element ist (das steht natürlich im letzten drin 😃 )?



  • nein die größe ist im moment NOCH nicht wichtig...
    warum sollte der aufrufer probleme bekommen? ich habs zwar noch nicht probiert, aber es wird best. lustig 😃
    du hast schon recht...
    aber das interessiert mich jetzt weniger als die eigentliche frage ||oben^^



  • Du meinst:

    temp = a.mult(b); //mecker....
    

    Wo hier der Copy-Constructor aufgerufen wird?
    Laut Deiner Fehlermeldung:

    /home/dgrat/Documents/vektor/src/vektor.cpp:76: error: vektor::vektor(vektor&)
    /home/dgrat/Documents/vektor/src/vektor.cpp:136: error: initializing argument 1 of `vektor vektor::mult(vektor)'

    für b.
    Warum?
    Du übergibst an mult eine Kopie des Vektors. Mal abgesehen davon, dass das teuer wird wenn die Vektoren gross werden, wird für das Anlegen der Kopie der Copy-Ct. benötigt. In Wirklichkeit macht der Compiler daraus (Pseudo-Code):

    Vektor& Vektor::mult( Vektor& x);  // so "denkt der Compiler es sich"
    
    Vektor x(b); // hier der Copy-Ctr das generiert er, weil Du eine Kopie haben willst
    temp = a.mult(x); // jetzt kann er die Referenz übergeben, ohne das Du b in der Funktion modifizieren kannst
    

    Dasselbe gilt bei Deiner Klasse auch für:

    a.mult(2).sub(c.mult(2)).add(d.mult(2))
    


  • mhh, danke erstmal für die geduld, aber das bsp, hat nur irgendwie nicht unter dev gefunzt.. obwohl compiler sehr zuverlässig sind unter linux dann aber doch!
    folgendes hat nicht funktioniert:

    temp = a.mult(b.mult(2) );
    

    und weil

    "b.mult(2)"
    

    eben sowas wie

    "b"
    

    ist, hat mich das gewundert... .
    aber du hast ja jetzt gut erklärt wo der c-ctr. aufgerufen wird, danke. 🙂
    der c-ctr wird also bei sämtlichen kopiervorgängen aufgerufen die klasseneigene objekte betreffen, egal ob direkt mit dem ctr. oder mit einer member-fkt. 😕



  • ssm schrieb:

    exigoner schrieb:

    float* vektor::get_vektor()
    {
           v = new float[3+1];
           v[0] = x;
           v[1] = y;
           v[2] = z;
           v[3] = 4; //groeße
           return v;
           delete [] v;
    }
    

    😮 😮 😮

    frag mich grad, warum du v returnst, also raus gehst aus der Methode und danach (obwohl du gar nicht mehr drin bist, den Speicher für v frei gibst... naja, wird schon seine Gründe haben, steht da net irgendwo vom Compiler irgendsowas wie: Waring: Unreachable Code
    ?



  • nein der gcc, warnt mich nicht. ich hab das gemacht weil ich irggendwo gelesen habe, dass ich mit new allokierten speicher wieder frei geben muss. also sollte ich wohl diese variable im destruktor delete'n und im konstruktor allokieren, oda->sicher...
    aber ich hatte keine lust soviel zu schreiben.

    ist diese aussage nun richtig?

    der c-ctr wird also bei sämtlichen kopiervorgängen aufgerufen die klasseneigene objekte betreffen, egal ob direkt mit dem ctr. oder mit einer member-fkt.

    dann weiß ich wenigstens wann i9ch diese referenzen benötige wenn ich nen eigenen c-ctr. mache.



  • jo, wäre auf jeden Fall besser, die im Konstruktor zu allokieren und im Destruktor zu deallokieren, als die Anweisung hinter ner Anweisung stehen zu lassen, bei der se sowieso nie an kommt



  • zum "zweiten" thema
    warum verwendest du kein union

    union
    {
    	struct
    	{
    		float	x, y, z, w;
    	} m;
    	float		val[4];
    };
    
    float *vektor::get_vektor() { return &val[0]; }
    


  • weil ich es nicht kenne,... 🙄 ist das schlimm?



  • exigoner schrieb:

    weil ich es nicht kenne,... 🙄 ist das schlimm?

    es würde auf jedenfall einige probleme lösen bzw ein paar sachen vereinfachen.
    bsp: du bräuchtest keinen dynamischen speicher
    zum thema union siehe: http://tutorial.schornboeck.net/union.htm



  • ich weiß nicht so recht... ist union nicht ein überbleib-sel aus vergangenen c-zeiten 🙄
    ich kann mir vorstellen, dass der code vielleicht unübersichtlich wird. wie oft/wo wendet ihr sowas an? immer da wo ihr auf new und delete verzichten wollt?
    in meinen programm wär das auf jeden fall eine interessante alternative.

    ps: ich nehme mal aufgrund fehlender einwände an, dass meine aussage bezüglich des c-ctr. richtig war. [hopefully]



  • miller_m schrieb:

    es würde auf jedenfall einige probleme lösen bzw ein paar sachen vereinfachen.
    bsp: du bräuchtest keinen dynamischen speicher
    zum thema union siehe: http://tutorial.schornboeck.net/union.htm

    Welchen Gewinn hat man durch die union? Ein struct würde es doch auch tun. Ich hoffe, Du willst die Union nicht zum casten missbrauchen. Dein Link zeigt das z.B. im 2. Beispiel auch falsch. Nur auf das letzte zugewiesene Element der Union darf zugriffen werden (mit einer Ausnahme für POD-Structs). (9.5)



  • exigoner schrieb:

    wie oft/wo wendet ihr sowas an?

    in meinen vektor klassen in den ich zeiger auf das erste element benötige 😉

    exigoner schrieb:

    immer da wo ihr auf new und delete verzichten wollt?

    das eine hat eigentlich nicht nichts mit den anderen zu tun

    exigoner schrieb:

    in meinen programm wär das auf jeden fall eine interessante alternative.

    sehe ich genau so

    exigoner schrieb:

    ps: ich nehme mal aufgrund fehlender einwände an, dass meine aussage bezüglich des c-ctr. richtig war. [hopefully]

    deine aussage ist für mich eigentlich nichts sagend. denn es wohl klar das wenn
    du kopierst wird er aufgerufen.
    wichtig ist nur das du entscheiden musst wann du kopieren willst und wann nicht.



  • das glaub ich nicht, wie soll ich mir das array im uniun dann vorstellen, 4 zeilen lan und nur w gespeichert?



  • 7H3 N4C3R schrieb:

    Welchen Gewinn hat man durch die union?

    hauptsächlich schreibarbeit und die gewissheit das im array das selbe steht
    wie in den werten des structs. und ich kann einfach einen pointer auf das erste element zurückgeben

    7H3 N4C3R schrieb:

    Ich hoffe, Du willst die Union nicht zum casten missbrauchen.

    😕
    nein, wie kommt man auf so eine idee 😃

    7H3 N4C3R schrieb:

    Dein Link zeigt das z.B. im 2. Beispiel auch falsch. Nur auf das letzte zugewiesene Element der Union darf zugriffen werden (mit einer Ausnahme für POD-Structs). (9.5)

    was meinst du? shades beispiel 😕



  • Den Link den du gepostet hast. Siehe Standard Sektion 9.5.


Anmelden zum Antworten