Kopierkonstruktor Call by Value



  • Hallo,
    wenn ich ein Objekt per all by Value an eine Funktion übergebe wird ja ein Temporäres Objekt erzeugt. Das ist ja soweit logisch. Aber wieso wird er hier ein 2. Mal aufgerufen:

    func(x)
    

    der Return wert wird ja verworfen.

    hier ist es wieder klar:

    klasse y=func(x)
    

    hier schon wieder nicht:

    y=func(x)
    

    ich hoffe mir kann geholfen werden.



  • Paule S schrieb:

    Hallo,
    wenn ich ein Objekt per all by Value an eine Funktion übergebe wird ja ein Temporäres Objekt erzeugt. Das ist ja soweit logisch. Aber wieso [...]

    Kann man nicht beantworten. Du hast zu wenig Informationen gegeben. Gib mal komplette Beispiele und nicht nur so kleine Code-Fetzen an.



  • klasse func(klasse test) {return test;}
    

    Kopierkonstruktor:

    klasse(const klasse& o): y(o.x), x(o.y) {
    		cout << "Copy" << endl;
    	}
    

    Oder was brauchst du noch? Die klasse hat nur die 2 int variablen x und y.



  • Das ist arg karg, die Info die du uns gibst.
    Sind die beiden Methoden identisch?

    func(x);
    klasse y = func(x);
    

    Kannst du da mal mehr Infos rausrücken, am besten ein Beispiel wo alle Funktionen und Typen bekannt sind.

    // edit: Nachdem ich zu langsam war:
    Das Statement "return" kopiert das Objekt in jedem Fall nochmal für die Rückgabe, egal ob du den Wert verwirfst oder verwendest.



  • Paule S schrieb:

    klasse func(klasse test) {return test;}
    

    Kopierkonstruktor:

    klasse(const klasse& o): y(o.x), x(o.y) {
    		cout << "Copy" << endl;
    	}
    

    Oder was brauchst du noch? Die klasse hat nur die 2 int variablen x und y.

    Ich tue jetzt einfach mal so, als wenn Deine main so aussehen würde:

    int main() {
      Klasse x;
      cout << "-----\n";
      func(x);                 // 1
      cout << "-----\n";
      Klasse y = func(x);      // 2
      cout << "-----\n";
      y = func(x);             // 3
    }
    

    Bei mein Compiler (GCC) kommt dabei folgendes raus:
    1. 2mal copy ctor
    2. 2mal copy ctor
    3. 2mal copy ctor und 1mal operator= anwenden

    Das ist jeweils eine Kopie x-->test und eine Kopie für test-->return_wert. Der C++ Standard erlaubt unter gewissen Umständen das "Verschmelzen" von Quell- und Ziel-Objekt, weil damit unnötige Kopien vermieden werden können (engl: "copy elision"). In diesem Fall erlaubt der C++ Standard das Verschmelzen von "test" und dem Return-Wert. Das kann aber kein Compiler und daher bekommst Du immer zwei Kopien hier, statt einer.

    Es gibt noch einen anderen netten Fall:

    func(Klasse(42));
    

    ...ein entsprechender Konstruktor vorausgesetzt. Hier sollte ein guter Compiler das Programm so übersetzen, dass der copy ctor nur höchstens einmal aufgerufen wird (nämlich zur Kopie von test -> Return-Wert). Das temporäre Objekt Klasse(42) darf und mit "test" "verschmolzen" werden.

    Weiteres Stichwort aus dem Bereich "copy elision": "return value optimization".



  • krümelkacker schrieb:

    Bei meinem Compiler (GCC) kommt dabei folgendes raus:
    1. 2mal copy ctor
    2. 2mal copy ctor
    3. 2mal copy ctor und 1mal operator= anwenden

    Das ist jeweils eine Kopie x-->test und eine Kopie für test-->return_wert. Der C++ Standard erlaubt unter gewissen Umständen das "Verschmelzen" von Quell- und Ziel-Objekt, weil damit unnötige Kopien vermieden werden können (engl: "copy elision"). In diesem Fall erlaubt der C++ Standard das Verschmelzen von "test" und dem Return-Wert. Das kann aber kein Compiler und daher bekommst Du immer zwei Kopien hier, statt einer.

    Ich vergaß zu erwähnen, dass im zweiten Fall

    Klasse y = func(x);
    

    Dein Compiler anscheinend auch den Return-Wert der Funktion mit y "verschmelzt". Sonst würdest Du sogar mehr als zwei Copy-Ctor-Aufrufe beobachten. Das kann man u.a. hier nachlesen, siehe §12.8/15.



  • @Paule S:
    Der Debugger ist dein Freund.
    Beispiel basteln, Haltepunkt in den copy-ctor, "go" drücken, und gucken wo der copy-ctor aufgerufen wird.
    Eigentlich ganz einfach.


Anmelden zum Antworten