Lifetime eines zurückgegebenen Objektes
-
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
du gibst keine adresse, sondern eine kopie von res zurück.
funktionslokale objekte müssen als rückgabewert kopiert werden. rückgabe als referenz oder pointer ist falsch. funktionslokaler speicher ist nicht mehr gültig, wenn die funktion verlassen wurde.
-
Was schreibt ihr hier von Kopien? Es wird nicht bei jeder Rückgabe etwas kopiert, siehe auch https://en.wikipedia.org/wiki/Copy_elision
Schau auch mal hier https://en.cppreference.com/w/cpp/language/copy_elision nach NRVO.
-
@stud123 sagte in Lifetime eines zurückgegebenen Objektes:
@manni66 wenn ich es nicht darf, wieso funktioniert es denn?
Wie kammt man von ausdrücklich vorgesehen auf nicht dürfen? Das ist mit völlig schleierhaft. Du darfst und sollst das.
-
@Wade1234
Ja schon, aber die Kopie wurde in der Zeile 11 erstellt und "lebt" im Scope bis zu Zeile 15. Danach gibt es die Adresse auf die Kopie zwar nach wie vor, (weil ja returnt), jedoch ist dieser Adressblock (in dem sich Complex res; befindet ) nicht mehr für dieses Objekt reserviert und kann bspw von einer lokalen Variablen oder von einem Objekt neu beschrieben werden?--> also sowas wie dangling pointer.
In Java bspw "lebt" ein Objekt bis keine Referenz auf dieses Objekt mehr existiert und wird dann (evtl.) vom Garbage Collector zerstört. In C++ wird beim verlassen des aktuellen Scopes der Speicherplatz freigegeben, egal ob nun eine Adresse darauf zeigt oder auch nicht.
Korrigiert mich bitte wenn ich was falsch gelernt habe
-
@stud123 Mit c3 in
main
gibt es aber einen neuen Speicherplatz.
Dorthin wird das Object (der Inhalt) beim return kopiert.Das ist kein Unterschied zu einem
int
oderdouble
-
Danke, das wollte ich hören
Lg
-
@stud123 sagte in Lifetime eines zurückgegebenen Objektes:
Danke, das wollte ich hören
LgGleich die erste Antwort sagt das aus:
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
bzw. in zeile 14 wird eine kopie von res erstellt,
Und in der zweiten Antwort auch nochmal.
@manni66 sagte in Lifetime eines zurückgegebenen Objektes:
So wie in deinem Code ist es aber ausdrücklich vorgesehen. Ein selbst geschriebener Typ kann genauso verwendet werden wie ein int.
Was dachtest du, was c3 ist/macht?
-
Füge mal noch folgenden Kopierkonstruktor zu deiner Klasse hinzu:
Complex(const Complex &other) //: real(other.real), imag(other.imag) { cout << "copy constructor" << endl; }
Durch Einkommentieren der 2. Zeile erhältst du dann auch die korrekte Kopie, aber zum Testen für dich lass es ersteinmal so laufen (so daß du dann ein falsches (zufälliges) Ergebnis erhältst).
Wenn du im Debugger den Code im Einzelschrittmodus laufen läßt, dann siehst du auch, daß der Kopierkonstruktor erst beimreturn res
aufgerufen wird.
-
@Th69 sagte in Lifetime eines zurückgegebenen Objektes:
Wenn du im Debugger den Code im Einzelschrittmodus laufen läßt, dann siehst du auch, daß der Kopierkonstruktor erst beim
return res
aufgerufen wird.Oder auch nicht.
Wie ich schon sagte, wird der normalerweise wegoptimiert. Es wird dann vom operator+ direkt in deine Variable c3 geschrieben! Man muss z.B. den g++ schon mit -fno-elide-constructors zwingen, das nicht zu tun. Sogar mit -O0 wird der sonst in diesem Beispiel wegoptimiert (hier ein g++ 7.4.0).
-
Im Debug-Modus ohne Optimierungen aber nicht (zumindestens im VS mit dem MSVC).
-
selbst wenn: sobald da cout drin steht, wird gar nichts wegoptimiert.
-
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
selbst wenn: sobald da cout drin steht, wird gar nichts wegoptimiert.
Die Ausage ist falsch!
-
@manni66 sagte in Lifetime eines zurückgegebenen Objektes:
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
selbst wenn: sobald da cout drin steht, wird gar nichts wegoptimiert.
Die Ausage ist falsch!
ja aber die programmausgabe, dass da ein kopiervorgang stattfand, muss ja erhalten bleiben. der compiler kann sowas ja nicht einfach entfernen.
-
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
ja aber die programmausgabe, dass da ein kopiervorgang stattfand, muss ja erhalten bleiben. der compiler kann sowas ja nicht einfach entfernen.
Lies irgendeinen der Links, die ich hier gepostet habe, und ändere deine Meinung.
-
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
@manni66 sagte in Lifetime eines zurückgegebenen Objektes:
@Wade1234 sagte in Lifetime eines zurückgegebenen Objektes:
selbst wenn: sobald da cout drin steht, wird gar nichts wegoptimiert.
Die Ausage ist falsch!
ja aber die programmausgabe, dass da ein kopiervorgang stattfand, muss ja erhalten bleiben. der compiler kann sowas ja nicht einfach entfernen.
Die Ausage ist falsch!
-
Doch, s. den schon von @wob geposteten Link zu Copy elision: Return value optimization.
Aber ohne aktivierten Optimierungen (bzw. mit speziellen Compiler-Flags) sollte der Kopierkonstruktor aufgerufen werden.
-
@Th69 sagte in Lifetime eines zurückgegebenen Objektes:
sollte der Kopierkonstruktor aufgerufen werden
Nein, er darf aufgerufen werden. Und stünde dort ein
return Complex ...
ist es ab C++ 17 garantiert, dass er nicht aufgerufen wird.
-
@stud123 sagte in Lifetime eines zurückgegebenen Objektes:
@manni66 wenn ich es nicht darf, wieso funktioniert es denn?
Dass "du es darfst" wurde ja schon beantwortet, womit sich diese Frage auch erübrigt.
Trotzdem der Hinweis: diese Frage solltest du dir bei C++ ganz schnell abgewöhnen. In C++ gibt es haufenweise Dinge die du nicht machen darfst, die aber oft genug zumindest scheinbar funktionieren werden.
Ganz einfaches Beispiel: es funktioniert oft genug auf Member eines Objekts das bereits zerstört und freigegeben wurde zuzugreifen. So lange bis es dann halt irgendwann nicht funktioniert und du einen unerwarteten Wert zurückbekommst oder dir das Programm bei dem Zugriff abstürzt.
Was auch ein ganz schlimmer Fehler ist den viele Anfänger und leider auch einige alte Hasen machen, ist zu versuchen zu verstehen wozu ein bestimmtes Verbot überhaupt da ist, und die Fälle aufzulisten in denen etwas schief gehen könnte. Und dann zu sagen "OK, in meinem Programm kann eh keiner dieser Fälle vorkommen, also ist das OK wenn ich es trotzdem mache". Lass das bleiben. Das führt dich und deine Kollegen über kurz oder lang bloss in eine Welt des Schmerzes.