Rückgabewerte
-
martiy2 schrieb:
Danke für die schnelle Antwort CStoll!
CStoll schrieb:
martiy2 schrieb:
Abend!
Ich habe 2 Fragen zu Rückgabewerten:
- Sagen wir ich habe eine Funktion, die eine Klasse by Value liefert:
Data getData();Wenn ich die nun einfach so fange:
Data d = getData();Dann wird da doch vermutlich 2mal der CopyCtor aufgerufen, oder? Einmal um das Objekt zu returnen und dann um d zu konstrieren aus dem returnten Objekt.
Wäre dann das hier performanter und empfehlenswerter?
const Data& d = getData();Ja, dort hast du normalerweise zwei Kopien, wobei der Compiler das auch wegoptimieren kann (Stichwort (N)RVO)
Die Alternative wird vermutlich nicht funktionieren, weil du dort eine Referenz auf eine temporäre Variable anlegst, die im nächsten Moment vernichtet wird.Meinst du mit Alternative das hier?:
Data getData(); const Data& d = getData();Das ist also gefährlich oder wie?
Ja, das ist gefährlich: Der Compiler legt eine temporäre Variable an, um den Rückgabewert aufzunehmen. Diese Variable wird am Ende der Anweisung wieder vernichtet. Wenn du eine Referenz auf diese Variable aufhebst, zeigt diese anschließend nur auf Datenmüll.
(mit NRVO spart der Compiler diese temporäre Variable ein und verwendet die lokale Variable, die aus der Funktion zurückgegeben wurde - aber die überlebt auch nicht länger)Bei der map<> liegt der Fall ein wenig günstiger - der Index-Operator gibt eine Referenz auf das Element zurück, da überlebt das referenzierte Objekt lange genug, um damit arbeiten zu können (zumindest solange du es nicht löschst).
EOutOfResources schrieb:
CStoll schrieb:
Edit @EOutOfResources: Das funktioniert aber nur, wenn die Funktion keine lokalen Werte zurückgibt

Bei einer Funktion die mit "get" beginnt...
Auch eine get-Funktion könnte die zurückgegebenen Werte lokal berechnen

-
Ok, dann schreibe ich also einfach
Data foo = getData();
und bete, dass der Compiler NRVO anwendet?Ich frage nur deshalb, weil der CopyCtor von Data ziemlich aufwändig ist.
-
martiy2 schrieb:
Ich frage nur deshalb, weil der CopyCtor von Data ziemlich aufwändig ist.
Nein. Aufwändig ist er sicher nicht! Vielleicht ist er aufwendig.
-
EOutOfResources schrieb:
martiy2 schrieb:
Ich frage nur deshalb, weil der CopyCtor von Data ziemlich aufwändig ist.
Nein. Aufwändig ist er sicher nicht! Vielleicht ist er aufwendig.
Er wollte nur sagen, daß dazu Aufwend betrieben wird.
-
volkard schrieb:
Er wollte nur sagen, daß dazu Aufwend betrieben wird.

-
EOutOfResources schrieb:
martiy2 schrieb:
Ich frage nur deshalb, weil der CopyCtor von Data ziemlich aufwändig ist.
Nein. Aufwändig ist er sicher nicht! Vielleicht ist er aufwendig.
Ein kurzes googlen verrät dir: dank neuer Rechtschreibung ist der Kommentar totaler Käse.
-
Irgendwie ist EOutOfResources schon extrem peinlich. Erst postet er schwachsinniges Zeugs, dann will er Klugscheißen und Rechtschreibflamen und schießt auch noch ein rießiges Eigentor und jetzt isser sogar zu blöd um das zu merken. Was für ein Clown.
-
AmüsierterMitleser schrieb:
Erst postet er schwachsinniges Zeugs,
Wo?
AmüsierterMitleser schrieb:
jetzt isser sogar zu blöd um das zu merken.
Wo?
-
Dann möchte ich noch http://www.duden.de/definition/einwenden einwänden.
-
Omg, selbst jetzt rafft er es noch nicht

EOutOfResources schrieb:
AmüsierterMitleser schrieb:
Erst postet er schwachsinniges Zeugs,
Wo?
Alles bis jetzt? Der falsche Tipp mit der const Referenz beim get. Der falsche Movesemantics tipp, den du nachträglich wegeditiert hast.AmüsierterMitleser schrieb:
jetzt isser sogar zu blöd um das zu merken.
Wo?
Du hast das Posting von volkard offenbar noch immer nicht verstanden. Oh man.
-
martiy2 schrieb:
Ok, dann schreibe ich also einfach
Data foo = getData();
und bete, dass der Compiler NRVO anwendet?Ich frage nur deshalb, weil der CopyCtor von Data ziemlich aufwändig ist.
Das wäre die sinnvollste Methode. Ich erwarte eigentlich von jedem modernen Compiler, dass er die Kopie an dieser Stelle zumindest mit entsprechenden Optimierungsschaltern unterlässt und das Objekt gleich an der richtigen Stelle konstruiert.
Übrigens - nur um das richtigzustellen:
Data getData(); const Data& d = getData();ist legaler Code. Die Zerstörung des temporären Objektes (des Rückgabewertes) wird hier verzögert, so lange die Referenz besteht. Nachzulesen im Standard, 12.2 (5). Wichtig dabei ist, dass es nur um die ursprüngliche Referenz geht. Beispielsweise kannst du nicht
struct foo { foo(Data const &data) : data_(data) { } Data const &data_; }; foo f(getData());schreiben, weil das temporäre Objekt nach Ende des Kopierkonstruktors - also wenn die Referenz, an die es usrprünglich gebunden wurde, seine Gültigkeit verliert - zerstört wird. Die genauen Regeln im Standard sind einigermaßen komplex, und es steht nicht zu erwarten, dass man mit diesem Trick auf neueren Compilern Laufzeit sparen kann, also kann ich diese Praxis nicht empfehlen. Gleichwohl ist sie prinzipiell erlaubt.
-
AmüsierterMitleser schrieb:
Irgendwie ist EOutOfResources schon extrem peinlich. Erst postet er schwachsinniges Zeugs, dann will er Klugscheißen und Rechtschreibflamen und schießt auch noch ein rießiges Eigentor und jetzt isser sogar zu blöd um das zu merken. Was für ein Clown.
Self level?
Gibt so´n Spruch mit Glashaus und Stein und so...