Zeiger als Parameter von Funktionen
-
Naja, ich nutze immer noch rohe Zeiger.
Wenn ich bspw. eine Klasse habe, die einen änderbaren, ab und zu auch mal ungültigen Verweis auf eine andere Klasse braucht.
-
Ethon schrieb:
Sone schrieb:
Ethon schrieb:
Rohe Zeiger sollten gänzlich vermieden werden. Es heißt nicht, dass man in der Praxis keinen Gebrauch davon macht. Im Gegenteil. Aber man benutzt Referenzen eher als Standard, und Zeiger nur wenn man dazu gezwungen wird.
Finde ich nicht. Ich benutze Zeiger sehr gerne wenn ich verdeutlichen möchte dass nur eine Referenz und kein Wert gespeichert wird, weil das mit der C++-Referenzen-Syntax leicht untergehen kann.
Und das kompensiert die Nachteile, die Zeiger mit sich bringen? Glaube ich nicht.
Welche Nachteile bitte?
Beispielsweise die hohe Fehleranfälligkeit durch falsche Initialisierung.
Bei einem so trivialen Fall wie deinem macht es allerdings wohl keinen Unterschied.
P.S.: Was, wenn durch deinen Code der Eindruck entsteht, deine Klasse führt im Destruktordeleteauf dem Zeiger aus (managt also den Speicher, der dynamisch allokiert sein sollte)?Nathan schrieb:
Naja, ich nutze immer noch rohe Zeiger.
Wenn ich bspw. eine Klasse habe, die einen änderbaren, ab und zu auch mal ungültigen Verweis auf eine andere Klasse braucht.Ja, da wirst du zu sowas gezwungen. Das ist in Ordnung.
-
Ethon schrieb:
Welche Nachteile bitte?
dass du immer auf NULL prüfen musst?
-
Sone schrieb:
Den String per Referenz entgegenzunehmen könnte je nach Benutzer meines Codes zu dem Irrtum führen, hier würde ein String kopiert (was meistens auch zu erwarten ist).
Hä? Was schert dich was der Benutzer denken könnte oder nicht?
Wenn ich eine Klasse schreibe ist es in meinem Interesse dass man damit nicht ganz so viel Scheiße anstellt.
Bar getBar() { string foo = makeFoo(); return Bar(foo); }vs
Bar getBar() { string foo = makeFoo(); return Bar(&foo); }Bei Zweiterem wird jeder, der moderneren C++ Code gewöhnt ist stutzig.
Bei Ersterem würde ich erwarten dass hier kopiert wird.
-
Bei Ersterem würde ich erwarten dass hier kopiert wird.
Ja, aber da du gesunden Menschenverstand hast, wirst du immer zuerst die Dokumentation lesen, wo groß und fett steht, wie das ganze Implementiert wurde, um Missverständnisse zu vermeiden.
-
edit: Mist
-
daddy_felix schrieb:
Ethon schrieb:
Welche Nachteile bitte?
dass du immer auf NULL prüfen musst?
Muss ich das? In den allermeisten Fällen wird ein nullptr absichtlich übergeben und wer absichtlich eine API falls benutzt ... naja.
Beispielsweise die hohe Fehleranfälligkeit durch falsche Initialisierung.
Ich kann einen Pointer genau wie eine Referenz verwenden, mit syntaktischen Unterschieden.
-
Sone schrieb:
Nathan schrieb:
Naja, ich nutze immer noch rohe Zeiger.
Wenn ich bspw. eine Klasse habe, die einen änderbaren, ab und zu auch mal ungültigen Verweis auf eine andere Klasse braucht.Ja, da wirst du zu sowas gezwungen. Das ist in Ordnung.
Aber selbst da nutze ich zur Initialisierung eine Referenz, damit mir kein DAU da einen nullptr reinfrimmelt...
-
Nathan schrieb:
Sone schrieb:
Nathan schrieb:
Naja, ich nutze immer noch rohe Zeiger.
Wenn ich bspw. eine Klasse habe, die einen änderbaren, ab und zu auch mal ungültigen Verweis auf eine andere Klasse braucht.Ja, da wirst du zu sowas gezwungen. Das ist in Ordnung.
Aber selbst da nutze ich zur Initialisierung eine Referenz, damit mir kein DAU da einen nullptr reinfrimmelt...
Natürlich. Oder könnte der User deiner Klasse vielleicht denken, es wird kopiert? Dann nimm doch lieber Zeiger. Unsicherer, aber Hauptsache keine falschen Implikationen...
-
Ethon schrieb:
daddy_felix schrieb:
dass du immer auf NULL prüfen musst?
Muss ich das? In den allermeisten Fällen wird ein nullptr absichtlich übergeben und wer absichtlich eine API falls benutzt ... naja.
lol
wenn du wüsstest, wie oft wir uns hier mit Nullpointern rumschlagen, die eben *nicht* absichtlich übergeben wurden...
void MyFunction(std::string* str) { // mach was mit str ohne Überprüfung } std::string* myString = GetSomeString(); MyFunction(myString);Wenn jetzt GetSomeString() aus irgendeinem Grund NULL zurückliefert, knallt es.
-
Ethon schrieb:
daddy_felix schrieb:
Ethon schrieb:
Welche Nachteile bitte?
dass du immer auf NULL prüfen musst?
Muss ich das? In den allermeisten Fällen wird ein nullptr absichtlich übergeben und wer absichtlich eine API falls benutzt ... naja.
Der hat seinen gesunden Menschenverstand nicht benutzt und nicht in die Doku geschaut, s.o.
Ethon schrieb:
Beispielsweise die hohe Fehleranfälligkeit durch falsche Initialisierung.
Ich kann einen Pointer genau wie eine Referenz verwenden, mit syntaktischen Unterschieden.
Ich kann auch ein Fahrrad wie ein Auto verwenden, mit Straßenverkehrsordnungsspezifischen Unterschieden.
-
daddy_felix schrieb:
Ethon schrieb:
daddy_felix schrieb:
dass du immer auf NULL prüfen musst?
Muss ich das? In den allermeisten Fällen wird ein nullptr absichtlich übergeben und wer absichtlich eine API falls benutzt ... naja.
lol
wenn du wüsstest, wie oft wir uns hier mit Nullpointern rumschlagen, die eben *nicht* absichtlich übergeben wurden...
void MyFunction(std::string* str) { // mach was mit str ohne Überprüfung } std::string* myString = GetSomeString(); MyFunction(myString);Wenn jetzt GetSomeString() aus irgendeinem Grund NULL zurückliefert, knallt es.
Hier sehe ich den Fehler aber bei GetSomeString()

Bei mir entstehen keine nullptr, die nicht absichtlich erzeugt wurden.Wenn die Funktion fehlschlagen kann, dann würde ich eine Exception werfen.
Wenn es normal ist dass Funktion einen ungültigen Wert zurückgeben kann, dann wäre das je nach Kontext ein Iterator oder boost::optional.Sone schrieb:
Ethon schrieb:
daddy_felix schrieb:
Ethon schrieb:
Welche Nachteile bitte?
dass du immer auf NULL prüfen musst?
Muss ich das? In den allermeisten Fällen wird ein nullptr absichtlich übergeben und wer absichtlich eine API falls benutzt ... naja.
Der hat seinen gesunden Menschenverstand nicht benutzt und nicht in die Doku geschaut, s.o.
Ethon schrieb:
Beispielsweise die hohe Fehleranfälligkeit durch falsche Initialisierung.
Ich kann einen Pointer genau wie eine Referenz verwenden, mit syntaktischen Unterschieden.
Ich kann auch ein Fahrrad wie ein Auto verwenden, mit Straßenverkehrsordnungsspezifischen Unterschieden.
1. Es gibt immer Leute, die nicht in die Doku schauen. Trotzdem ist das ein schwer auffindbarer Bug, der so leicht zu vermeiden ist.
2. Nicht alles was hinkt ist ein Vergleich
... sorry, aber eine Referenz und ein Pointer unterscheiden sich nur geringfügig.
-
sorry, aber eine Referenz und ein Pointer unterscheiden sich nur geringfügig.
Jein. Ein Zeiger speichert eine Adresse. Eine Referenz referenziert ein Objekt. Wo ist da, ganz technisch, die Gemeinsamkeit?
Klar, ihr Zweck ist letzten Endes ähnlich.Edit: Nein, auch das nicht, jedenfalls nicht immer.
-
Ethon schrieb:
Wenn die Funktion fehlschlagen kann, dann würde ich eine Exception werfen.
ohoh, das ist aber gefährlich. Woher soll denn der DAU wissen, dass deine Funktion fehlschlagen könnte und dann eine Exception wirft?
Sag jetzt bitte nicht "Doku", denn
Ethon schrieb:
1. Es gibt immer Leute, die nicht in die Doku schauen.
-
Sone schrieb:
sorry, aber eine Referenz und ein Pointer unterscheiden sich nur geringfügig.
Jein. Ein Zeiger speichert eine Adresse. Eine Referenz referenziert ein Objekt. Wo ist da, ganz technisch, die Gemeinsamkeit?
Klar, ihr Zweck ist letzten Endes sehr ähnlich.Du weißt schon dass du auch bei Zeigern von Referenzierung/Dereferenzierung sprichst oder?
Eine Referenz verhält sich syntaktisch wie ein bestehendes Objekt (wurden sie deswegen nicht sogar eingeführt? Wegen der Syntax der Operatorenüberladung ?) und sie muss zwingend mit einem Objekt initialisiert werden. Ansonsten sind sie gleich.
Im Compileroutput ist eine Referenz nicht von einem Zeiger zu unterscheiden, das ist reiner Syntaxzucker.daddy_felix schrieb:
Ethon schrieb:
Wenn die Funktion fehlschlagen kann, dann würde ich eine Exception werfen.
ohoh, das ist aber gefährlich. Woher soll denn der DAU wissen, dass deine Funktion fehlschlagen könnte und dann eine Exception wirft?
Sag jetzt bitte nicht "Doku", denn
Ethon schrieb:
1. Es gibt immer Leute, die nicht in die Doku schauen.
Dann wird der Exception vermutlich bis in die Main durchrauschen und es gibt eine schöne Fehlermeldung und der Nutzer weiß es.

Im meinem Fall wäre es eine Referenz, die mitten in den Stack zeigt. Das ist ganz böse.
-
Ethon schrieb:
Eine Referenz verhält sich syntaktisch wie ein bestehendes Objekt (wurden sie deswegen nicht sogar eingeführt? Wegen der Syntax der Operatorenüberladung ?) und sie muss zwingend mit einem Objekt initialisiert werden. Ansonsten sind sie gleich.
Im Compileroutput ist eine Referenz nicht von einem Zeiger zu unterscheiden, das ist reiner Syntaxzucker.Der Compileroutput interssiert mich meistens nicht. Wenn er mich interessieren würde, kann ich auch gleich wieder C programmieren. In C++ ist eh fast alles syntaktischer Zucker.
Referenzen unterscheiden sich nicht nur syntaktisch sondern auch semantisch doch recht erheblich voneinander.
Referenzen stellen über ihre gesamte Lebensdauer ein Alias auf ein Objekt dar. Zeiger können während ihrer Lebensdauer auf viele verschiedene Objekte, auf ein definiert ungültiges Objekt, oder auf irgendetwas zeigen. Ich finde, das sind genügend Unterschiede.