Referenz als Rückgabe
-
Nur dann wenn es notwändig (EDIT: nein, das schreibt man nicht so :D) ist.
z.B.
- Wenn das Objekt nicht kopierbar ist.
- Wenn die Referenz gebraucht wird um das Objekt zu verändern (oder allgemein: wenn das Objekt nicht kopiert werden darf, weil sich sonst das Verhalten des Programms ändern würde).
- Wenn man eine Stelle isoliert hat wo es einfach "zu teuer" ist ein Objekt die ganze Zeit zu kopieren.
Bei (1) und (3) aber auch erstmal an boost::shared_ptr<> oder ähnliches denken.
Grund: mit Referenzen kann man IMO schneller Mist bauen als mit Kopien als Rückgabewert. Kopien sind einfacher zu verstehen. Kopien können nicht auf Objekte zeigen die schon nichtmehr existieren. Kopien können nicht "hinterrücks" von anderen Threads verändert werden. Kopien werden nicht beim Aufruf irgendeiner Funktion überraschend ihren Wert ändern. Kopien sind gut, Kopien sind dein Freund

-
Bei den Nachteilen von Referenzen kann ich nur zustimmen.
Es ist schon bitterböse wenn man überall Referenzen oder Pointer benutzt und somit theoretisch jede Funktion das Objekt verändern kann. In solchen Fällen braucht man eine sinnvolle Doku für jede Funktion, welche unter anderem angibt welche Parameter verändert wird und welche nicht. Aus dem Grund hat ja Microsoft in seiner Doku überall ein [in], [out] vor den Parametern-Doku stehen.
-
Beachten muss man auch unbedingt, keine Referenzen auf lokale Objekte einer Funktion zurückzugeben. Das ist schneller passiert als man denkt

-
Ich denke auch, dass man das hald in jedem Fall gut überlegen muss/sollte. (Wie eigentlich praktisch alles, was man schreibt).
Eigentlich sollte man so wenig Möglichkeiten geben, etwas "böses" zu machen. (Wie oben schon gesagt). Also nur etwas zusätzlich geben, wenn man einen guten Grund dazu hat.btw:
hustbaer schrieb:
notwändig
Sorry, aber, als ich das gelesen habe..

Hat mich irgendwie an den Erdbären erinnert..
-
Rofl, bin ich doof. Ich wende, du wendest, er/sie/es wendet, ...
Muss ich das jetzt 100x auf die Tafel schreiben?
p.S.: ärdbäären

-
mikey schrieb:
Beachten muss man auch unbedingt, keine Referenzen auf lokale Objekte einer Funktion zurückzugeben. Das ist schneller passiert als man denkt

Keine Ahnung also mir ist sowas noch nie passiert.
Wenn man den Sinn eines Objektes in einer Funktion kennt, dann sollte das auch nicht passieren.
-
wenn du ein neues objekt allokierst über die funktion (prototyping pattern, factory pattern, etc) gib einen pointer zurück, das verdeutlicht dass du in charge bist dich um dieses objekt zu kümmern und es irgendwann wieder zu löschen
wenn du in einer klasse selbst member variablen hast die pointer auf andere objekte sind und du möchtest sie über getter methoden holen würde ich sie als referenzen zurückgeben, dann kommt niemand auf die idee diese objekte zu deleten
das argument dass wenn man nicht mit kopien arbeitet alles alles verändern kann (da es ja referenzen/pointer sind) find ich schlecht
ich will garnicht anfangen von speicher oder performance oder sowas zu reden sondern:
gerade wenn man kopien zurück und übergeben würde hätte man vllt als anwender die illusion man verändert das objekt wirklich - würde aber nur die kopie verändern
das kann schnell zu schwer auffindbaren bugs führen
dasselbe bei parametern, ich finde eine faustregel ist dass eingabeparameter auch wirklich eingabeparameter sein sollte und nicht mehr
was ich damit meine ist dass sowas wiedouble CalculateSomething(int aValue) { aValue /= sqrt(PI); return aValue; }falsch ist, aValue ist ein eingabeparameter und sollte nicht als variable verwendet werden
wenn man sich an sowas hält dann unterlaufen einem nicht so leicht blöde fehler (wenn die funktion länger wäre will ich später vllt auf aValue zugreifen wieder und bräuchte den ursprungswert aber ich hab aValue schon verändert - wenn aValue nich sowas leichtes wäre wie ein integer sondern eine instanz einer klasse würde man überhaupt noch schwieriger drauf kommen)
von da her macht es auch sinn eingabeparameter immer als const zu markieren und als referenz zu übergeben finde ich (außer vllt bei native datentypen, da find ich ist es ein overhead und übergebe sie einfach als int etc und achte einfach darauf sie nicht als variablen sondern als eingabeparameter zu verwenden)
wenn ich etwas aber als rückgabeparameter verwenden möchte (weil ich einen pointer auf das objekt übergebe und es in der funktion zb allokiere) dann halt ein pointer
ähnlich bei durchlaufparametern (wenn also der sinn der funktion ist das objekt wirklich auch zu verändern) - allerdings ist es bei denen geschmackssache ob man sie als referenzen oder pointer übergibt
man muss sich halt für sich selbst überlegen wo es sinn macht pointer und wo referenzen zu verwenden
-
hustbaer schrieb:
Rofl, bin ich doof. Ich wende, du wendest, er/sie/es wendet, ...
Muss ich das jetzt 100x auf die Tafel schreiben?
p.S.: ärdbäären

Ach..das war keine Absicht?!..

Na dann. Mindestens 1'000'000 mal. Aber ich gebe dir einen kleinen Tipp.

http://travian-projekt.de/travian/img/stuff/NiceTry.gifbtt:
Ansonsten mache ich das so ähnlich, wie Vevusio. An erster Stelle einfach mal sehr viel nachdenken, was man da so machen könnte, dass es nicht so rauskommt, wie ich es will. Und dann das verhindern.
-
-
ich würde immer dann Referenzen auf Objekte zurückgeben, wenn es Arbeit erspart. Es wird doch bei jedem überladenem << operator für ostream eine Referenz zurückgegeben. Ähnliche Situationen gibt es auch wo anders auch häufig. Oft kann man es auch bei so Uni-Aufgaben verwenden, wo man so ein Stack implementieren soll, wenn hier die methoden eine Referenz auf das Objekt selbst zurückliefern, kann das Schreibarbeit, sowie Platz sparen, wenn man verschiedene Operationen mit dem Stack verknüpfen möchte.