Wann by Pointer und wann by Reference
-
1312 schrieb:
Kann doch jeder programmieren wie er will. Die einen machen sich halt hundert Gedanken vorher und halten jede Regel ein, versuchen dazu immer ein DP mit rein zu quetschen und den denken dann noch nach wie sie den Code zu Tode generalisieren könnten und die anderen sind in der Zeit schon fast fertig.
Und während die einen Bugs innerhalb von Stunden fixen und neue Features innerhalb von einigen Tagen einbauen, blickt bei den anderen nach einem halben Jahr keiner mehr durch den Code durch.
-
daddy_felix schrieb:
Und während die einen Bugs innerhalb von Stunden fixen und neue Features innerhalb von einigen Tagen einbauen, blickt bei den anderen nach einem halben Jahr keiner mehr durch den Code durch.
Und besonders schön ist, wenn man Code von Anderen übernehmen muss, und man vorgeworfen bekommt wie langsam man doch sei (Kryptischer Code, 5fach Zeiger, keine Kommentare und bei Fragen an den betreffenden Entwickler: "Schau in den Code"). Besonders schön ist auch wenn man Variablen undeutlich bezeichnet, und die von drei Codestellen unterschiedlich gesetzt werden (Dem Entwickler ist zwar bekannt das globale Variablen nur mit Bedacht eingesetzt werden sollen, sein Ersatz waren dann aber beispielsweise 50 public static Member in einer Sammelklasse...).
Grundsätzlich sollte man sich einen sauberen Code angewöhnen, auch wenn man dies unter Zeitdruck etc. nicht immer hin bekommt. Wenn man im Stil von "1312" programmiert kann man für sich im eigenen Kämmerchen entwickeln, aber man sollte die Finger von Projekten lassen bei denen mehr als eine Person arbeitet.
-
Und wie genau übertragen sich die hier genannten Gruselszenarien auf die Frage, ob man Referenzen oder Zeiger verwenden sollte?
-
SeppJ schrieb:
Pointer nur, wenn es irgendeinen Grund geben könnte, dass dieser Null ist. Was so gut wie nie der Fall sein wird. Daher: Referenz, außer es gibt einen sehr guten Grund dagegen.
Das ist die Sicht des Aufgerufenen.
Aus Sicht des Aufrufers
"Pointer, wenn ich erlaube, daß der Aufgerufene was ändert. Const-Ref oder Kopie, wenn ich es nicht erlaube." Ich sehe im Code des Aufrufers am & immer sofort, daß da was heikel ist.Beim Aufrufer mache ich Fehlerfreiheit. Der Aufgerufene ist schon fehlerfrei.
-
knivil schrieb:
1312 schrieb:
Kann doch jeder programmieren wie er will. Die einen machen sich halt hundert Gedanken vorher und halten jede Regel ein, versuchen dazu immer ein DP mit rein zu quetschen und den denken dann noch nach wie sie den Code zu Tode generalisieren könnten und die anderen sind in der Zeit schon fast fertig.
In professioneller Umgebung schreibt man Code nicht fuer sich allein. Dort kann nicht jeder programmieren wie er will.
Es gibt aber genug Leute die nicht im Team arbeiten, gerade bei C++. Wenn ich allein ein kleines Tool schreibe, dann fange ich nicht an mir gedanken über OOP oder const zu machen. Da wird einen kurze Skizze gemacht und das Ding in ein paar Tagen fertig gemacht. Aber meist landet man bei der Sprachenwahl eher nicht bei C++.
-
volkard schrieb:
Aus Sicht des Aufrufers
"Pointer, wenn ich erlaube, daß der Aufgerufene was ändert. Const-Ref oder Kopie, wenn ich es nicht erlaube." Ich sehe im Code des Aufrufers am & immer sofort, daß da was heikel ist.Ohne diese Technik mal angewendet zu haben, der positive Effekt des &-Zeichens ist nur lokal. Wenn ich 10 Funktionen habe, die sich gegenseitig mit dem gleichen Argument aufrufen, dann habe ich einmal am Anfang die Dereferenzierung und ab dann werden immer Pointer rumgereicht. Aber was, wenn ich auch mitten im Chain wissen will, ob das Objekt verändert wird?
-
ausrufer schrieb:
Aber was, wenn ich auch mitten im Chain wissen will, ob das Objekt verändert wird?
Dann musst du einen Objektzustand pflegen, anders geht es nicht. Weder Zeiger noch Referenzen sagen einem ob ein Zustand verändert wird, sondern geben einen nur die Option. Das einzige was man in einer Schnittstelle hervorheben kann ist, ob diese Funktion einen Wert ändern kann oder nicht (nicht ob sie es auch tut).
Zur Ausgangsfrage noch mein Senf:
Zeiger nutze ich wenn ich muss (z.B. null_ptr ist zulässig), Referenzen wenn ich kann (und in beiden Fällen nach Möglichkeit bei den nicht-veränderlichen Teilen const).
-
asc schrieb:
Dann musst du einen Objektzustand pflegen, anders geht es nicht. Weder Zeiger noch Referenzen sagen einem ob ein Zustand verändert wird, sondern geben einen nur die Option. Das einzige was man in einer Schnittstelle hervorheben kann ist, ob diese Funktion einen Wert ändern kann oder nicht (nicht ob sie es auch tut).
Du hast ihn falsch verstanden. Was er meinte:
void code() { int a = 4, b = 5; funktion(a, &b); // volkard: Man erkennt Veränderung von b } void funktion(int a, int* b) { funktion2(a, b); // ausrufer: Man erkennt Veränderung NICHT mehr } void funktion2(int a, int* b);Das ist ein gutes Argument, auch wenn strikt gesehen das Objekt selbst (also der Zeiger vom Typ
int*) nicht geändert wird. Um die Erkennbarkeit von Veränderungen beim Aufruf konsequent durchzusetzen, müsste man Zeiger speziell kennzeichnen. Aber dann wären wir bei UN angelangt...Ich persönlich verwende Referenzen, wenn ich kann. Ein weiterer Grund für sie ist, dass sie Code lesbarer halten, wenn viele Dereferenzierungen vorkommen. Schlimm wirds bei der Kombination mit anderen Operatoren, z.B.
(*container)[index].
-
void code() { int a = 4, b = 5; funktion(a, &b); // volkard: Man erkennt Veränderung von b } void funktion(int a, int* b) { funktion2(a, b); // ausrufer: Man erkennt Veränderung NICHT mehr //irgendwie doch ein wenig, hier ist halt der ganze *b heikel. }
-
volkard schrieb:
//irgendwie doch ein wenig, hier ist halt der ganze *b heikel.Ist nicht immer der ganze b heikel? Ich kann den Vorteil deiner Technik in "funktion" immer noch nicht erkennen.