Copy Konstruktoren und = operator



  • moin
    Warum darf ich nicht folgendes machen:

    TKlasse::TKlasse(const TKlasse& ref) //Copy Konstructor
    {
      *this = ref;
    }
    
    TKlasse& TKlasse::operator = (const TKlasse& ref)  
    { 
      [...]//irgendwelche zugriffe auf private Object Variablen um zu kopieren
      return *this;
    }
    

    Der Code funktionier zwar soll aber nicht immer gehen.

    mfg



  • Konstructor haben seit C98 KEINEN rueckgabe type!
    Gilt auch fuer den destructor...

    Fuer den operator=() why not?



  • Hi!

    TKlasse& TKlasse::operator = (const TKlasse& ref)   
     { 
       [...]//irgendwelche zugriffe auf private Object Variablen um zu kopieren 
       return *this; 
     }
    

    Warum darfst du das nicht machen? Wer sagt das? Der Compiler? Wenn ja, würde ich gern mal wissen was genau er zu beanstanden hat!

    grüße



  • Gandalfus schrieb:

    moin
    Warum darf ich nicht folgendes machen:

    TKlasse::TKlasse(const TKlasse& ref) //Copy Konstructor
    {
      *this = ref;
    }
    

    weil es dein programm tötet. du rufst den op= nit einem linken argument auf, das gar nicht initialisiert ist (das noch gar kein lebendes objekt ist).
    in *this=ref wird zum beispiel vorher was gelöscht. der einfachheit halber mach ich mal den op= ohne copy&swap.

    UString::UString(const UString& ref) //Copy Konstructor
    {
      *this = ref;
    }
    UString& operator=(UString& ref){
       if(&ref==this) return *this;
       delete[] mem;//kill!
       mem=new char[strlen(ref.mem)+1];
       strcpy(mem,ref.mem);
       return *string;
    }
    
    TKlasse& TKlasse::operator = (const TKlasse& ref)  
    { 
      [...]//irgendwelche zugriffe auf private Object Variablen um zu kopieren
      return *this;
    }
    

    Der Code funktionier zwar soll aber nicht immer gehen.

    der geht immer.



  • volkard schrieb:

    UString& operator=(UString& ref){
       if(&ref==this) return *this;
       delete[] mem;//kill!
       mem=new char[strlen(ref.mem)+1];
       strcpy(mem,ref.mem);
       return *string;
    }
    

    Soll das jetzt ein Beispiel dafür sein, wie man es nicht macht oder wie muss ich dich da verstehen?

    Ein op= ohne swap sollte dann eher so aussehen:

    UString& operator=(const UString& ref)
    {
        char* tmp = new char[strlen(ref.mem)+1];
        strcpy(tmp,ref.mem);
        delete[] mem;//kill!
        mem = tmp;
        return *this;
    }
    


  • volkard schrieb:

    weil es dein programm tötet. du rufst den op= nit einem linken argument auf, das gar nicht initialisiert ist (das noch gar kein lebendes objekt ist).

    Wenn ich den Konstruktor auf rufe ist das object doch instanziert. Sonst könnte ich im Konstruktor ja auch nicht auf Object Variablen zugreifen.

    Mein Ziel ist dass ich keine redundanten code habe.



  • Gandalfus schrieb:

    Wenn ich den Konstruktor auf rufe ist das object doch instanziert. Sonst könnte ich im Konstruktor ja auch nicht auf Object Variablen zugreifen.

    falsch. ruf doch mal ne viruelle funktion auf und du wirst sehen, daß dein objekt noch nicht lebt.

    Mein Ziel ist dass ich keine redundanten code habe.

    sag das doch gleich.
    benutze copy&swap.

    friend void swap(UString& a,UString& b){
       swap(a.data,b.data);
    }
    UString& operator=(const UString& ref)
    {
        UString tmp(ref);
        swap(*this,tmp);
        return *this;
    }
    

    übrigens steht U für Unfug und ist eine parodie auf dein T.


  • Mod

    Gandalfus schrieb:

    volkard schrieb:

    weil es dein programm tötet. du rufst den op= nit einem linken argument auf, das gar nicht initialisiert ist (das noch gar kein lebendes objekt ist).

    Wenn ich den Konstruktor auf rufe ist das object doch instanziert. Sonst könnte ich im Konstruktor ja auch nicht auf Object Variablen zugreifen.

    Mein Ziel ist dass ich keine redundanten code habe.

    bei copy-konstruktion wird ein neues objekt initialisiert. beim copy-op= dagegen muss zunächst der alte inhalt des objekts zerstört werden, bevor es als kopie des arguments neu initialisiert wird. und hier liegt das problem: wenn die zerstörung des alten inhalts nicht trivial ist, insbes. bestimmte invarianten erfüllt sein müssen, dann ist es logischerweise nicht möglich, ein objekt, das nicht explizit initialisiert wurde, zu benutzen. was C++ angeht, so ist ein objekt fertig konstruiert, sobald der konstruktor-körper ausgeführt wird, deshalb wird dich der compiler auch niemals an obigem konstrukt hindern. unter logisch-semantischen gesichtspunkten ist es dagegen ein grober fehler. im gegensatz dazu geht copy&swap den umgekehrten weg: hier wird op= mittels des copy-ctors implementiert. redundanz zu vermeiden, ist ein sinnvolles ziel, allerdings in der gegenwärtigen sprache (in abwesenheit von ctor-delegation) ohnehin nicht immer zu vermeiden, insofern sollte es an dieser stelle auch nicht unbedingt top-priorität haben.


Anmelden zum Antworten