Wann wird Zuweisungsoperator aufgerufen und wann der Copy C'tor ?



  • Hallo Leute ich hab da mal eine kurze Frage ..

    Wann genau wird der Copy C'tor aufgerufen und wann der Zuweisungsoperator ?
    •int function(ClassType _instance); // Copy C'tor ?
    •ClassType instance(_instance); // Copy C'tor ?
    •ClassType instance = _instance ; // Wird hier der Copy C'tor oder operator = aufgerufen ?
    •instance = _instance // Hier wird doch eigentlich der = operator aufgerufen , in einigen Foren stand hier dass der Copy C'tor aufgerufen wird , aber warum ?

    Ich hoffe ihr könnt meine Unklarheiten beseitigen 😞

    Greets



  • Immer wenn ein neues Objekt erstellt wird, wird ein Konstruktor aufgerufen. Das heißt in deinem Fall 1-3 CTor und 4 AssignOp.

    Edit: Bei Fall 1 ist natürlich dann eigentlich function(blub) gemeint. Da wird blub nun kopiert weil es call-by-value ist.

    Bei Fall 4 steht das nur dann im Internet mit CopyCTor wenn eigentlich Fall 3 gemeint ist.

    MfG SideWinder



  • Ok , 1 2 und 4 sind mir klar .
    Aber warum wird bei :

    ClassType Instance = _Instance der Copy Konstruktor aufgerufen und nicht der Zuweisungsoperator ?
    Ich gebe doch sogar explizit an dass ich zuweisen möchte . 😕
    Ist das compilerintern so festgelegt dass er hier anstatt des = ope. den Copy C'tor aufruft weil es scheller ist ?
    Denn würde ich:

    ClassType instance;
    instance = _instance
    

    schreiben , müsste er ja einmal den Standard C'tor und dann nochmal den Zuweisungsoperator aufrufen .
    Ist meine Annahme richtig ?

    Greets



  • Nicht compilerintern ist das festgelegt sondern im ISO-Standard. Und ja, weil es natürlich schneller ist.

    Würdest du das unten schreiben, ja, dann müsste beides aufgerufen werden.

    MfG SideWinder



  • Bacid90210 schrieb:

    Denn würde ich:

    ClassType instance;
    instance = _instance
    

    schreiben , müsste er ja einmal den Standard C'tor und dann nochmal den Zuweisungsoperator aufrufen .
    Ist meine Annahme richtig ?

    Ja. Das ist aber nicht mehr äquivalent zu

    ClassType instance = _instance;
    

    Letzteres ist eine sogenannte Kopierinitialisierung. Im übrigen ist das dasselbe wie bei der Initialisierung von Funktionsparametern.



  • Eine Frage hab ich dann noch .
    Nehmen wir mal an ich habe eine Oberklasse und eine Klasse die von dieser erbt.
    Meine Unterklasse hat keine Member . Meine Oberklasse besitzt 2 oder 3.
    Wenn ich jetzt nur einen Copy C'tor für meine Oberklasse implementiert habe und keinen für meine Unterklasse , erzeugt der Compiler dann auch einen default Copy C'tor für die Unterklasse welcher die übergeben Instanz an den Copy C'tor der Oberklasse weiterleitet ?



  • Guten Abend,

    Weder Basisklasse noch abgeleitete Klasse besitzen einen Copy-Konstruktor:
    Basisklassenobjekt und das Objekt der abgeleiteten Klasse werden durch eine bitweise Kopie initialisiert.

    Beide haben einen Copy-Konstruktor:
    Basisklassenobjekt und das Objekt der abgeleiteten Klasse werden durch Copy-Konstruktor initialisiert.

    Die Basisklasse hat einen, aber die abgeleitete Klasse nicht:
    Basisklassenobjekt wird durch den Copy-Konstruktor initialisiert, das Objekt der abgeleiteten Klasse durch eine bitweise Kopie initialisiert.

    Die abgeleitete Klasse hat einen, aber die Basisklasse nicht:
    - Basisklassenobjekt wird durch eine bitweise Kopie initialisiert, aber nur dann, wenn im Copy-Konstruktor der abgeleiteten Klasse explizit der Copy-Konstruktor der Basisklasse aufgerufen (Initialisierungsliste) wird. Ansonsten wird der Standardkonstruktor der Basisklasse aufgerufen.
    - Das Objekt der abgeleiteten Klasse wird durch den Copy-Konstruktor initialisiert.

    Allerdings, macht es überhaupt Sinn, nur den der Basisklasse zu implementieren, oder nur den der abgeleiteten Klasse?

    lg



  • Heißt das jetzt dass wenn ich beide Copy Konstruktoren implementiert habe im Copy C'tor der abgeleiteten Klasse den Copy C'tor der Oberklasse nicht explizit aufrufen muss ? Ja oder ... ?



  • Die abgeleitete Klasse hat einen, aber die Basisklasse nicht:
    - Basisklassenobjekt wird durch eine bitweise Kopie initialisiert, aber nur dann, wenn im Copy-Konstruktor der abgeleiteten Klasse explizit der Copy-Konstruktor der Basisklasse aufgerufen (Initialisierungsliste) wird. Ansonsten wird der Standardkonstruktor der Basisklasse aufgerufen.
    - Das Objekt der abgeleiteten Klasse wird durch den Copy-Konstruktor initialisiert

    Wie soll ich denn den Copy Konstruktor explizit aufrufen wenn ich gar keinen definiert habe ? 😕
    Generiert mir der Compiler also einen Standard Copy Konstruktor ?

    abgeleitete Klasse hat einen, aber die Basisklasse nicht



  • Es gibt 4 Dinge, die jede Klasse immer hat:

    1. Defaul-Konstruktor
    2. Copy-Konstruktor
    3. Destruktor
    4. Zuweisungsoperator

    Falls du diese nicht explizit definierst, generiert sie der Compiler, wobei der Rumpf dieser spziellen Methoden dann natürlich leer ist.

    PS: In meinem vorherigen Post habe ich mit "er besitzt einen" natürlich einen explizit definierten gemeint.

    lg



  • Bacid90210 schrieb:

    Heißt das jetzt dass wenn ich beide Copy Konstruktoren implementiert habe im Copy C'tor der abgeleiteten Klasse den Copy C'tor der Oberklasse nicht explizit aufrufen muss ? Ja oder ... ?

    Richtig, es wird automatisch gemacht... es wird immer zuerst das Objekt der Basisklasse erstellt und danach das Objekt der abgeleiteten Klasse. Beim Destruktor ist es umgekehrt, da wird immer zuerst das Objekt der abgeleiteten Klasse zerstört, und dann das der Basisklasse.

    lg



  • @Gugelmoser:

    Aua aua aua.

    Man kann - bis auf den Destruktor - alle von dir aufgeführten Dinge unterdrücken, so dass eine Klasse nichts davon hat.
    Es ist auch nicht unüblich das zu machen, z.B. um Objekte unkopierbar zu machen (siehe boost::noncopyable).

    Und bei RAII haste oft Klassen die man nicht Default-Instanzieren kann (=die nur Konstruktoren haben die Parameter brauchen).
    RAII Klassen sind auch meistens gleichzeitig "noncopyable", d.h. die haben dann alle 3 von dir genannten Dinge nicht.

    Weder Basisklasse noch abgeleitete Klasse besitzen einen Copy-Konstruktor:
    Basisklassenobjekt und das Objekt der abgeleiteten Klasse werden durch eine bitweise Kopie initialisiert.

    NEIN,
    in dem Fall haben die Basisklasse und die abgeleitete Klasse einen implizit definierten Konstruktor, der wiederum alle implizit definierten Konstruktoren der Basisklassen und Member aufruft.
    Soll heissen, hier wird nix bitweise Kopiert (wäre auch fatal):

    class Base
    {
        std::string m_a_string;
    };
    class Derived : public Base
    {
        std::string m_another_string;
    };
    


  • hustbaer schrieb:

    Man kann - bis auf den Destruktor - alle von dir aufgeführten Dinge unterdrücken, so dass eine Klasse nichts davon hat.

    Ok, da würde mich nun interessieren wie man das genau anstellt?

    hustbaer schrieb:

    NEIN,
    in dem Fall haben die Basisklasse und die abgeleitete Klasse einen implizit definierten Konstruktor, der wiederum alle implizit definierten Konstruktoren der Basisklassen und Member aufruft.
    Soll heissen, hier wird nix bitweise Kopiert (wäre auch fatal):

    Ok, das habe ich nun aus dem Vorlesungs-Skript meines Professors. Gut zu wissen dass das Quatsch ist :). Gibt es den dann überhaupt in irgendeinem Fall ein bitweises kopieren? Und wieso wäre das fatal?

    lg



  • Gugelmoser schrieb:

    hustbaer schrieb:

    Man kann - bis auf den Destruktor - alle von dir aufgeführten Dinge unterdrücken, so dass eine Klasse nichts davon hat.

    Ok, da würde mich nun interessieren wie man das genau anstellt?

    Indem du beispielsweise den CCTOR und copy-asignment-op einfach privat deklarierst.

    Gugelmoser schrieb:

    hustbaer schrieb:

    NEIN,
    in dem Fall haben die Basisklasse und die abgeleitete Klasse einen implizit definierten Konstruktor, der wiederum alle implizit definierten Konstruktoren der Basisklassen und Member aufruft.
    Soll heissen, hier wird nix bitweise Kopiert (wäre auch fatal):

    Ok, das habe ich nun aus dem Vorlesungs-Skript meines Professors. Gut zu wissen dass das Quatsch ist :). Gibt es den dann überhaupt in irgendeinem Fall ein bitweises kopieren? Und wieso wäre das fatal?

    lg

    Das string-Objekt hält beispielsweise einen pointer auf einen Speicherbereich wo die Zeichenkette abgespeichert wird.
    Würdest du nun bitweise kopieren, würdest du einfach die Speicheradresse kopieren, nicht aber die verwaltete Zeichenkette. Ändert dann Objekt1 die Zeichenkette, würde Objekt2 ebenfalls etwas von der Änderung mitbekommen (zeigt ja auf den gleichen Speicherbereich) - oder Objekt1 wird gelöscht - was ist dann mit Objekt2?



  • inter2k3 schrieb:

    Gugelmoser schrieb:

    hustbaer schrieb:

    Man kann - bis auf den Destruktor - alle von dir aufgeführten Dinge unterdrücken, so dass eine Klasse nichts davon hat.

    Ok, da würde mich nun interessieren wie man das genau anstellt?

    Indem du beispielsweise den CTOR und copy-asignment-op einfach privat deklarierst.

    Oder -zumindest für die Konstruktoren- einfach einen Konstruktor mit Parameter definierst.



  • inter2k3 schrieb:

    Gugelmoser schrieb:

    hustbaer schrieb:

    Man kann - bis auf den Destruktor - alle von dir aufgeführten Dinge unterdrücken, so dass eine Klasse nichts davon hat.

    Ok, da würde mich nun interessieren wie man das genau anstellt?

    Indem du beispielsweise den CTOR und copy-asignment-op einfach privat deklarierst.

    Naja, dann kann ich aber immernoch innerhalb der Klasse darauf zugreifen. Von dem her würd ich sowas nicht als "unterdrücken" bezeichnen, schließlich sind sie ja immernoch da...

    lg



  • @Jockelx: Das verhindert ja nicht das Generieren eines CCTORS oder assignment-ops, sondern nur das Generieren eines def. CTORS.

    @Gugelmoser: Nein - sie sind ja nur deklariert, nicht definiert.



  • inter2k3 schrieb:

    @Gugelmoser: Nein - sie sind ja nur deklariert, nicht definiert.

    achso, so hast du das gemeint. Gut, dann hat man aber einen Linker-Error, falls man versucht, innerhalb der Klasse darauf zuzugreifen. Wenn ich nun von einem Programm ausgehe, das weder Syntax- noch Linker-Fehler aufweißt... hab ich dann nicht immer die "Großen Drei"?

    lg



  • Naja, du kannst sie ja auch definieren und lässt einfach die Initialisierungsliste weg bzw. den Rumpf leer.



  • inter2k3 schrieb:

    Das string-Objekt hält beispielsweise einen pointer auf einen Speicherbereich wo die Zeichenkette abgespeichert wird.
    Würdest du nun bitweise kopieren, würdest du einfach die Speicheradresse kopieren, nicht aber die verwaltete Zeichenkette. Ändert dann Objekt1 die Zeichenkette, würde Objekt2 ebenfalls etwas von der Änderung mitbekommen (zeigt ja auf den gleichen Speicherbereich) - oder Objekt1 wird gelöscht - was ist dann mit Objekt2?

    Gut du redest nun von deep-copy oder? deep-copy hat man aber nur, wenn man entsprechend explizit definiert. Das vom Compiler generierte macht nur eine flat-copy (das Objekt hinter dem Zeiger wird nich kopiert).


Log in to reply