Rückgabe von Objekten



  • asc schrieb:

    Die meisten Referenzen die ich kenne, erwähnen diese nicht.

    Schön, aber was willst du damit ausdrücken? Dass du nichts von der Dokumentation von Kontrakten hältst oder wie?

    Wenn man die Preconditions bereits an der Deklaration erkennt, halte ich dies für eine bessere Wahl, als das man erst einmal die Dokumentation suchen muss.

    Man erkennt leider nicht an der Deklaration, ob Nullzeiger erlaubt sind oder nicht. Ansonsten siehe volkard.

    Bashar schrieb:

    Dann nimm halt eine C++-Funktion, die einen char-Pointer erwartet. Den Konstruktor von ifstream z.B.

    Es gibt einen guten Grund warum die C++Funktionen im kommenden Standard in diesen Punkt umgestellt werden.

    Und du meinst, der Grund wäre, dass die Leute sich nicht darüber im klaren sind, dass man da keinen Nullzeiger übergeben darf? Du weichst der Frage aus.



  • Simon2 schrieb:

    Mein persönliches Kriterium war bislang immer: "Ist es nullable oder verschiebbar, nimm Zeiger; sonst Referenz."

    Meins ist: Referenzen nur wenns const-Referenzen sein können, also nur zum unsichtbaren beschleunigen.

    Allerdings kommt die Frage ja eh nur sehr selten auf und wird mit der Zeit immer seltener. Die Connection zum Beispiel wird vermutlich einen Konstruktor haben, der connected.



  • Simon2 schrieb:

    Mein persönliches Kriterium war bislang immer: "Ist es nullable oder verschiebbar, nimm Zeiger; sonst Referenz."
    (Was nicht bedeutet, dass das das beste/einzige/sinnvollste/... Kriterium sei - eben nur mein(bisherige)s).

    Sehe ich ähnlich. Und damit dokumentiert die Angabe Referenz/Zeiger auch, ob NULL zulässig ist oder nicht. Wenn es nicht änderbar sein soll hantiere ich zusätzlich mit const.



  • Ich versuche auch wenn möglich Referenzen zu verwenden. Ich finde nicht, dass es sich wegen dem Schneller Erkennen lohnt, einen Zeiger zu erlauben. Nicht nur, weil dann Null übergeben werden kann; bei einer Referenz ist auch garantiert, dass sie nicht geändert wird und bei der Initialisierung auf ein gültiges Objekt zeigen muss. Ein hübscher Nebeneffekt ist gerade, dass man sich die Dereferenzierungssyntax sparen kann. Wieso sollte ich einen Zeiger verwenden, wenn ich das Ganze mit Referenzen tun kann und damit mehr Einschränkungen möglich sind?

    Viele Funktionen, die man verwendet, kennt man entweder bereits, oder die IDE unterstützt einen beim Schreiben der Argumentliste, indem sie die Parametertypen mitteilt. Spätestens wenn ich da eine Referenz sehe, ist mir klar, dass das Objekt verändert werden kann. Dazu braucht es keinen Adressoperator beim Aufruf.


  • Administrator

    @Volkard,
    Mal noch ein ganz anderes Argument. Missbrauchst du grundsätzlich mit deinem Vorgehen nicht die Sprache? Du definierst für deinen Code, dass ein Zeiger immer auf ein veränderbares Objekt zeigt. Das stimmt aber von der Sprache her gar nicht.
    Wenn du mal eine Funktion hast, wo auch ein konstanter Nullzeiger übergeben werden kann, dann hast du genau das gleiche Problem, welches du verhindern wolltest. Das Objekt verändert sich nicht, obwohl du es ganz klar gekennzeichnet hast, dass es sich verändert.

    Ich halte das Programmieren gegen ein Sprachkonzept für nicht all zu klug.
    Wenn du solche Stellen wirklich kennzeichnen willst, dann verwende dazu lieber Kommentare. Dafür sind Kommentare schliesslich da und nicht ein Addressoperator.

    Bashar schrieb:

    Bevor ich so eine "Logik" anwende, würde ich mich über die Preconditions der Funktion schlaumachen.

    Naja, grundsätzlich können wir wohl sowieso davon ausgehen, dass jeder hier zuerst die Bibliothek durchlesen wird, bevor er anfängt mit ihr zu programmieren.

    Aber wir können auch davon ausgehen, dass man nicht für jede Funktion alles nochmals ganz genau nachschauen geht.

    Und ich bin mir auch ziemlich sicher, dass wenn ich in einer C++ Bibliotheksdokumentation lese, dass man einen Zeiger übergeben soll, aber ja keinen Nullzeiger, ich das folgende denken werde:
    "Was ist denn das für einen Unsinn???"

    😉

    Seit wann übergeben Benutzer Nullzeiger?

    Meinte den Benuzter der Bibliothek oder Funktion. Ein wenig blöd ausgedrückt, Programmierer wäre klarer gewesen.

    Grüssli



  • Dravere schrieb:

    Missbrauchst du grundsätzlich mit deinem Vorgehen nicht die Sprache?

    nein. ich bemühe mich, sie sinnvoll einzusetzen.

    Du definierst für deinen Code, dass ein Zeiger immer auf ein veränderbares Objekt zeigt. Das stimmt aber von der Sprache her gar nicht.
    Wenn du mal eine Funktion hast, wo auch ein konstanter Nullzeiger übergeben werden kann, dann hast du genau das gleiche Problem, welches du verhindern wolltest. Das Objekt verändert sich nicht, obwohl du es ganz klar gekennzeichnet hast, dass es sich verändert.

    Ich halte das Programmieren gegen ein Sprachkonzept für nicht all zu klug.
    Wenn du solche Stellen wirklich kennzeichnen willst, dann verwände dazu lieber Kommentare. Dafür sind Kommentare schliesslich da und nicht ein Addressoperator.

    ihr argumentiert immer aus der sicht des implementierers der funktion, scheint mir. oder allenfalls als der, der den funktionsaufruf einmal schreibt. ich argumentiere als benutzer, der den funktionsaufruf liest. und als benutzer, der hunderte von zeilen liest wenn er eine schreibt. ich lese eine größere funktion durch, weil da was mit con nicht stimmt und da steht eine zeile mit &con im aufruf und sofort ist der aufruf unter verdacht. und das senkt bei mir die zeit, die ich fürs debuggen brauche. ich verwende mehr zeit aufs fehlersuchen, als aufs bloße eintippen. ist das bei euch anders? und wenn es so ist, sollte da nicht das augenmerk auf reduktion der fehlersuchzeit gelegt werden?



  • Nexus schrieb:

    Viele Funktionen, die man verwendet, kennt man entweder bereits, oder die IDE unterstützt einen beim Schreiben der Argumentliste, indem sie die Parametertypen mitteilt. Spätestens wenn ich da eine Referenz sehe, ist mir klar, dass das Objekt verändert werden kann. Dazu braucht es keinen Adressoperator beim Aufruf.

    Naja, das Schreiben des Codes sehe ich eigentlich nicht so sehr als Problem, selbst dann nicht, wenn ich keine IDE habe, die mir unter die Arme greift, und ich die Funktion auch nicht "auswendig" kenne. So oder so muß ich ja eh die Bedeutung der einzelnen Parameter kennen, um die Funktion überhaupt benutzen zu können.

    Schwieriger finde ich es dann, wenn man alten Code nach Wochen/Monaten/Jahren nochmal liest, denn dann fehlt bei non-const-Referenzen jeglicher Hinweis darauf, daß der Parameter verändert wird.
    Das soll jetzt aber kein Argument sein, stattdessen Pointer zu benutzen, sondern das ist einfach nur eine beliebte Stolperfalle, die man ggf. in irgendeiner Form kenntlich machen sollte.



  • volkard schrieb:

    ihr argumentiert immer aus der sicht des implementierers der funktion, scheint mir. oder allenfalls als der, der den funktionsaufruf einmal schreibt. ich argumentiere als benutzer, der den funktionsaufruf liest. und als benutzer, der hunderte von zeilen liest wenn er eine schreibt. ich lese eine größere funktion durch, weil da was mit con nicht stimmt und da steht eine zeile mit &con im aufruf und sofort ist der aufruf unter verdacht. und das senkt bei mir die zeit, die ich fürs debuggen brauche. ich verwende mehr zeit aufs fehlersuchen, als aufs bloße eintippen. ist das bei euch anders? und wenn es so ist, sollte da nicht das augenmerk auf reduktion der fehlersuchzeit gelegt werden?

    Das kann ich jetzt durchaus verstehen. Mir persönlich fehlt da jetzt die jahrelange Nerverei, um das bestätigen zu können, klingt aber durchaus plausibel. Allerdings ist das im Alltag wirklich so üblich, dass die Funktionsnamen nicht schon genug verraten, was sie mit dem Parametern machen könnten?

    Zu dem Zeiger/Referenzen:
    Ich benutze Zeiger auch mit der Möglichkeit einen 0-Zeiger übergeben zu können wenn ich etwas optional einstellen will. Z.B trägt ein Mensch optional einen Hut. Und dann kann ich den per SetHut (Hut* h) setzen. Wenn ich da jetzt ein gültiges Objekt übergebe, dann wird der gezeichnet, oder was auch immer und wenn ich 0 übergebe, dann wird der deaktiviert. Sprich auch keine Aufrufe gemacht. Ein Dummy-Objekt, dass mir einen "leeren" Hut anzeigt finde ich nicht schön.



  • dooooomi schrieb:

    Schwieriger finde ich es dann, wenn man alten Code nach Wochen/Monaten/Jahren nochmal liest, denn dann fehlt bei non-const-Referenzen jeglicher Hinweis darauf, daß der Parameter verändert wird.
    Das soll jetzt aber kein Argument sein, stattdessen Pointer zu benutzen, sondern das ist einfach nur eine beliebte Stolperfalle, die man ggf. in irgendeiner Form kenntlich machen sollte.

    Irgendwie höre ich die ganze Zeit, dass man auch nach Monaten den Code noch verstehen soll.

    Es ist nun aber in jedem Falle so, dass man sich nach dieser Zeit wieder kurz einarbeiten muss. Das beinhaltet auch, dass man die Funktionen noch einmal anschaut, bei denen man sich nicht sicher ist. In vielen IDEs reicht ja ein Darüberfahren mit der Maus, bis man sieht: "Ah, die Funktion nimmt eine Referenz, das Objekt könnte verändert werden." Zudem ist ein guter Kommentar an der richtigen Stelle aus meiner Sicht oft hilfreicher als ein Adressoperator, der irgendwie an C und die Gegebenheit, dass tatsächlich ein Zeiger benötigt wird, erinnert.

    Edit: drakons Argument, dass der Funktionsname eigentlich aussagen sollte, was passiert, kann ich voll zustimmen.



  • Dravere schrieb:

    Bashar schrieb:

    Bevor ich so eine "Logik" anwende, würde ich mich über die Preconditions der Funktion schlaumachen.

    Naja, grundsätzlich können wir wohl sowieso davon ausgehen, dass jeder hier zuerst die Bibliothek durchlesen wird, bevor er anfängt mit ihr zu programmieren.

    Aber wir können auch davon ausgehen, dass man nicht für jede Funktion alles nochmals ganz genau nachschauen geht.

    Wenn man's im Kopf hat, muss man nicht nachschauen. Sonst schon, das würde ich erwarten.

    Und ich bin mir auch ziemlich sicher, dass wenn ich in einer C++ Bibliotheksdokumentation lese, dass man einen Zeiger übergeben soll, aber ja keinen Nullzeiger, ich das folgende denken werde:
    "Was ist denn das für einen Unsinn???"

    Und wenn du bei sqrt liest, dass man eine double-Zahl übergeben soll, die aber nicht negativ sein darf, denkst du das auch?



  • Bashar schrieb:

    Und wenn du bei sqrt liest, dass man eine double-Zahl übergeben soll, die aber nicht negativ sein darf, denkst du das auch?

    Naja, bei einem Zeiger besteht ja ein charakteristischer Punkt darin, dass er Null sein kann. Bei double würde ich nicht von vornerein davon ausgehen, dass der gesamte Wertebereich ausgenutzt wird.


  • Administrator

    @volkard,
    Ich argumentiere aus meiner Sicht, wenn ich eine fremde Bibliothek nutze. Also als Nutzer einer fremden Bibliothek.

    Die meiste Zeit verbrate ich oft beim Planen und erstellen von Graphiken und Abhängigkeiten. Schreiben des Codes geht meistens sehr schnell.
    Fehlersuche, die hat sich bei mir bisher kontinuierlich verkleinert. Aber ich achte beim schreiben des Codes sicher nicht darauf, dass ich weniger schreiben muss. Meistens schreibt ich viel mehr, als ich müsste, damit die Fehlersuche einfacher wird. Zum Beispiel schreib ich einen Kommentar hin 😉

    Dein Problem, dass sich ein Objekt verändert, obwohl es nicht sollte, löse ich wie folgt:
    Debugger anwerfen, Objekt beobachten lassen. Conditional Breakpoint setzen, wenn sich das Objekt verändert. Problemstelle gefunden, allenfalls mit dem Callstack noch ein paar Funktionen rauf gehen.
    Ich verwende halt einen sinnvollen Debugger. Den ganzen Code durchlesen empfinde ich als zu mühsam und langsam, der Debugger kann mir da viel schneller und viel genauere Informationen geben.

    Aber ich muss sagen, dass ich das jetzt schon seit Ewigkeiten nicht mehr hatte. Dank VAX + IntelliSense und einem sinnvollen Funktionsnamen habe ich immer sofort erkannt, wann das Objekt verändert wird und wann nicht.

    Man kann sich da teilweis auch etwas helfen, indem man das Objekt konstant macht, bevor man es irgendwo weitergibt, also zum Beispiel sowas:

    Connection connection;
    Connection const& constConnection = connection;
    
    function(constConnection);
    
    // Bzw. was ich oft mache und es vielleicht ein wenig sinnvoller aussieht.
    // Obwohl vec vielleicht nicht konstant ist:
    typename std::vector<T>::const_iterator iter = vec.begin();
    typename std::vector<T>::const_iterator end = vec.end();
    
    // Arbeiten mit den konstanten Objekten.
    

    @Bashar,
    Das geht aus dem Funktionsnamen hervor, dass die Zahl nicht negativ sein soll. Zudem gibt es keine Möglichkeit von der Sprache her, nur positive double zu erlauben.

    Grüssli



  • volkard schrieb:

    ihr argumentiert immer aus der sicht des implementierers der funktion, scheint mir. oder allenfalls als der, der den funktionsaufruf einmal schreibt.

    Nein. Ich argumentiere aus Sicht des Benutzers.

    Wenn ich eine Zeigerübergabe sehe, gehe ich in C++ im ersten Moment davon aus, das NULL zulässig ist. Bei einer Referenz stellt sich hier garnicht erst die Frage. Ebenso: wenn ich einen nicht-const Aufruf sehe, erwarte ich das die Funktion etwas ändert, dabei ist es irrelevant ob es sich um ein Zeiger oder eine Referenz handelt.

    Ich schaue maximal in die Deklaration einer Funktion (meist auch durch die IDE angezeigt), und erwarte das ich anhand der Parameter (dies schließt auch const ein) sowie der Funktions- und Parameterbezeichnung die Bedeutung ablesen kann. Wenn nicht, gibt es zwei weitere Punkte:
    a) Schauen ob eine Dokumentation vorhanden ist
    b) Refactoring bis die Funktion verständlich ist

    volkard schrieb:

    ich lese eine größere funktion durch, weil da was mit con nicht stimmt und da steht eine zeile mit &con im aufruf und sofort ist der aufruf unter verdacht.

    Ich sehe an &con weder, ob etwas geändert wird, noch ob NULL zulässig ist. Es heißt einfach nur das ein Zeiger übergeben wird. Ja, es gibt etwas das man vielleicht hätte in C++ besser machen können: Explizite Angabe der Verwendung bei dem Aufruf (wobei ich bezweifel das bei der typischen Schreibfaulheit einiger Programmierer dies gewünscht wäre). Nichts desto trotz ist deine Konvention nicht am Sprachstandard gedeckt, und daher verlasse ich mich grundsätzlich auf die Deklaration.

    Ganz davon abgesehen das ich "größere funktion" ohnehin als Designfehler ansehe. Eine Funktion sollte immer überblickbar sein. Ansonsten ist diese in sinnvoll überschaubare kleinere Funktionen aufzusplitten.

    volkard schrieb:

    und das senkt bei mir die zeit, die ich fürs debuggen brauche. ich verwende mehr zeit aufs fehlersuchen, als aufs bloße eintippen. ist das bei euch anders?

    Nein, aber sagt ein &con für mich rein garnichts aus, so das ich hier im Zweifel eh die Deklaration anschauen muss.

    volkard schrieb:

    und wenn es so ist, sollte da nicht das augenmerk auf reduktion der fehlersuchzeit gelegt werden?

    Grundsätzlich ja: Nur ziehe ich die Fehlermeldungen des Compilers immer der Fehlersuche vor (Siehe hier z.B. das Thema sprintf / stringstream), und ich erwarte in einem Projekt das die Methoden/Funktionen sinnvoll deklariert werden (ggf. noch durch Dokumentation ergänzt).

    Dazu gehört auch der sinnvolle Einsatz von Referenzen vs. Zeigern und const vs. nicht-const. Sowie die Verwendung von Konstrukten die tendenziell Fehler bereits zur Compilezeit, nicht erst zur Laufzeit sichtbar machen (sofern möglich).

    cu André



  • Dravere schrieb:

    @Bashar,
    Das geht aus dem Funktionsnamen hervor, dass die Zahl nicht negativ sein soll.

    Wenn du ein Problem mit konkreten Beispielen hast, stell dir eine Funktion f mit einem nichttrivialen Prädikat P als Vorbedingung vor. Ich dachte, dass anschauliche Beispiele vielleicht nicht ganz schlecht sind, aber eigentlich hätte mich das mit strlen und ifstream schon stutzig machen können :p

    Zudem gibt es keine Möglichkeit von der Sprache her, nur positive double zu erlauben.

    Es gibt auch keine Möglichkeit, Zeiger, die nicht null sein können, zu spezifizieren. (Nein, das ist nicht die Aufgabe von Referenzen.)


  • Administrator

    Bashar schrieb:

    Wenn du ein Problem mit konkreten Beispielen hast, ...

    Habe ich ja nicht. Es scheint eher, dass du Probleme hast, welche zu finden 😉

    Bashar schrieb:

    ... strlen ...

    Ist, wie schon einmal gesagt, eine C-Funktion. In C gibt es keine Referenzen und keine Objekte. Alle Strings sind als Zeiger vorhanden. Also gibt es gar keinen anderen Weg.

    Bashar schrieb:

    ... ifstream ...

    Ich weiss nicht wieso man das bei ifstream , fstream und ofstream gemacht hat, ist aber meiner Meinung nach ein Designfehler. Vielleicht hat man es aber auch aus Kompatibilitätsgründen zu C gemacht, weil Stringliterale nunmal mit Zeiger angesprochen werden.
    Interessanterweise wird dieser Designfehler nun "behoben".

    Ich möchte zudem zu dem Thema noch ein paar Dinge anfügen.

    Bisher hast du nur mit Funktionen argumentiert, welche einen C String erwarten. Da kommt man nunmal nicht um einen Zeiger herum.
    Zeig mir mal eine Funktion, wo ein Objekt von einer Klasse übergeben werden muss und dabei Zeiger verwendet werden, aber in der Dokumentation steht, dass der Zeiger nicht 0 sein darf.
    Da wirst du in der C++ Bibliothek wohl eher lange suchen.

    Andere Bibliotheken können das sicher haben, zum Beispiel welche von volkard. Aber das heisst ja nichts. Das heisst einfach nur, dass ich diese Bibliothek als unschön empfinden werde.

    Mir ist es daher ein wenig ein Rätsel, wieso du auf diesem Punkt so rumhackst und immer wieder Beispiele liefern willst, welche sowieso gar nichts bringen. Was willst du mit diesen Beispielen bezwecken?

    Bashar schrieb:

    Es gibt auch keine Möglichkeit, Zeiger, die nicht null sein können, zu spezifizieren. (Nein, das ist nicht die Aufgabe von Referenzen.)

    Nein, das ist wirklich nicht die Aufgabe von Referenzen. Sie erfüllen aber genau diese Bedingung bei der Übergabe an Funktionen. Genau das was man braucht.

    Grüssli



  • EOD für mich.



  • Dravere schrieb:

    Bashar schrieb:

    ... strlen ...

    Ist, wie schon einmal gesagt, eine C-Funktion. In C gibt es keine Referenzen und keine Objekte. Alle Strings sind als Zeiger vorhanden. Also gibt es gar keinen anderen Weg.

    Es ist eine C++ Funktion da sie im C++ Standard erwaehnt wird.

    Es waere trivial gewesen strlen(0) so zu definieren dass es etwas definiertes macht. zB 0 oder -1 zu liefern.

    Aber es ist nicht notwendig. Dafuer wurden naemlich preconditions erfunden. Auch damals als man es noch nicht preconditions nannte.

    Ein simples Beispiel fuer preconditions ist:

    ofstream s;
    s<<"foo";
    

    s<<"foo"
    ist eine precondition verletzung. Recht triviale Sache eigentlich.

    Bisher hast du nur mit Funktionen argumentiert, welche einen C String erwarten. Da kommt man nunmal nicht um einen Zeiger herum.

    Das ist aber eine komplette Themenverfehlung von dir. Denn es geht um Preconditions nicht um Zeiger.

    strlen(0) koennte einfach 0 liefern oder -1 oder 7. Es muss nur definiert werden.

    aber mal was anderes:
    std::vector<int> v;
    v[0]=3;

    ist das nicht was lustiges? Es ist wieder einmal eine precondition verletzung (oder besser gesagt invarianten verletzung, aber ich bin mal so frech und packe das zusammen).

    Zeig mir mal eine Funktion, wo ein Objekt von einer Klasse übergeben werden muss und dabei Zeiger verwendet werden, aber in der Dokumentation steht, dass der Zeiger nicht 0 sein darf.
    Da wirst du in der C++ Bibliothek wohl eher lange suchen.

    std::sort()

    der comparer darf nicht ein null zeiger sein, wohl aber ein zeiger.

    bekomm ich jetzt nen keks?

    Bashar schrieb:

    Es gibt auch keine Möglichkeit, Zeiger, die nicht null sein können, zu spezifizieren. (Nein, das ist nicht die Aufgabe von Referenzen.)

    Nein, das ist wirklich nicht die Aufgabe von Referenzen. Sie erfüllen aber genau diese Bedingung bei der Übergabe an Funktionen. Genau das was man braucht.

    Ich bin kein Fan von volkards variante mit zeigern fuer out parametern.
    aber das wirkliche Problem dass er angeht damit ist ein ziemlich akutes:

    c++ bietet nicht die moeglichkeit zwischen in, out und inout parametern zu unterscheiden. diese unterscheidung ist wichtig. wenn sie einem wirklich wichtig ist, dann ist die zeiger variante durchaus eine moegliche Loesung. uU wird es logischer wenn man

    #define OUT &
    connect(OUT con, "www.c++.de");
    

    schreibt

    aber das waere haesslich.

    Die Frage um die es hier gehen sollte ist ob & eine sinnvolle Kennzeichnung fuer out parameter ist. Denn Zeiger die nicht 0 sein duerfen gibt es oefters - jeder kennt die C Strings und weiss dass es hier sehr oft so ist. Der Grund warum es in der C++ Standard Library sehr wenige solche Beispiele gibt kommt einfach daher dass fast nirgendwo Zeiger verwendet werden. Aber an fast allen Stellen wo Zeiger verwendet werden sind 0 Werte verboten.

    zB das komplette iterator subsystem erlaubt keine 0 Zeiger. Einzig wo 0 zeiger erlaubt sind ist bei memory operationen. wobei ich jetzt auch nicht weiss was ein allocator::deallocate(0) macht... aber ein allocator::destroy(0) muesste UB sein...

    und das zieht sich durch die ganze c++ standard library. volkards methode out parameter als Zeiger setzen ist unueblich - aber Zeiger die nicht 0 sein duerfen sieht man ueberall wenn man die augen aufmacht.



  • Shade Of Mine schrieb:

    volkards methode out parameter als Zeiger setzen ist unueblich

    Sie wird auch von John Lakos ("Large Scale C++ Software Design") empfohlen.


  • Administrator

    Shade Of Mine schrieb:

    Es ist eine C++ Funktion da sie im C++ Standard erwaehnt wird.

    Können wir uns darauf einigen, dass die Funktion aus der C Bibliothek 1:1 übernommen wurde. Ok, noch einen Namensraum std drumrum. Ansonsten ist das eine C Funktion. Wenn ich mich recht erinnere, steht das glaub ich sogar im Standard, dass die Funktion aus der C Library ist 😉

    Shade Of Mine schrieb:

    ... preconditions erfunden ...

    Und eine Menge Beispiele mit Preconditions, aber hier ging es doch nie um Preconditions, oder habe ich was verpasst? Es ging doch um Zeiger übergeben zum Kennzeichnen von veränderbaren Objekten, statt einer Referenz, damit man keinen Nullzeiger übergeben darf.

    Die ganze Diskussion wird völlig aus dem Kontext gezogen.

    Shade Of Mine schrieb:

    bekomm ich jetzt nen keks?

    Ja, aber nur weil die hier gegessen werden müssen, sonst sind sie bald überfällig von Weihnachten her 😉

    Shade Of Mine schrieb:

    Ich bin kein Fan von volkards variante mit zeigern fuer out parametern.
    aber das wirkliche Problem dass er angeht damit ist ein ziemlich akutes:

    Das will ich nicht abstreiten, aber solche Kennzeichnungen kann man anders machen und anders berücksichtigen. Das wurde ja auch schon gesagt. Darum ging es hier ja eigentlich auch nicht. Es ging um das wie des Kennzeichnens.

    Shade Of Mine schrieb:

    Die Frage um die es hier gehen sollte ist ob & eine sinnvolle Kennzeichnung fuer out parameter ist.

    Genau! Du sprichst mir aus dem Herzen!

    Shade Of Mine schrieb:

    Denn Zeiger die nicht 0 sein duerfen gibt es oefters - jeder kennt die C Strings und weiss dass es hier sehr oft so ist.

    Und da kann man bekanntlich auch nicht anders. Wurde auch schon gesagt.

    Und es geht auch nicht um die Fehlerbehandlung, sondern es geht darum, dass man in C keine Referenzen verwenden konnte und erst recht nicht für C Strings. Es ging also um die Übergabe.

    Shade Of Mine schrieb:

    Der Grund warum es in der C++ Standard Library sehr wenige solche Beispiele gibt kommt einfach daher dass fast nirgendwo Zeiger verwendet werden.

    Wieso wurden aber teilweise keine Zeiger hingeschrieben und einfach eine Bedingung hingemacht, dass keine Nullzeiger übergeben werden dürfen? Vielleicht weil es unsinnig ist und keine "Nullobjekte" übergeben werden sollten?

    Bestes Beispiel sind da doch die swap Funktionen von den Containern. Wieso sollte man dort nicht einen Zeiger übergeben sollen. Würde doch gehen, wir müssen nur eine Precondition in die Dokumentation setzen, dass es kein Nullzeiger sein darf. 🤡

    Shade Of Mine schrieb:

    zB das komplette iterator subsystem erlaubt keine 0 Zeiger.

    Mit diesen Zeigern als Zeigern komme ich als Nutzer aber nie in Berührung? Diese Zeiger sind Bibliothek intern und abgeschlossen. Zudem ging es nicht um die Speicherung als Zeiger, sondern um die Übergabe bei einer Funktion.

    Ich übergebe zum Beispiel noch oft Referenzen, um dann deren Zeiger zu speichern. Der Zeiger in der Klasse darf kein Nullzeiger sein. Aber wie gesagt, darum geht es hier nicht.

    Shade Of Mine schrieb:

    Einzig wo 0 zeiger erlaubt sind ist bei memory operationen. wobei ich jetzt auch nicht weiss was ein allocator::deallocate(0) macht... aber ein allocator::destroy(0) muesste UB sein...

    Das Beispiel ist aber auch eher witzig. Das Objekt, mit welchem man hier arbeitet, ist der Zeiger. Logisch übergibt man dann einen Zeiger. Was man aber nicht macht, ist ein Zeiger auf einen Zeiger zu übergeben 😉

    Grüssli

    PS: Wer wettet, dass wir hier noch nicht am Ende der Diskussion sind? 🙂



  • Ich verstehe nicht ganz, wieso hier eine so ausufernde Diskussion entsteht 😕 Soweit ich weiß, hängt sich das Ganze doch an Volkards Anmerkung auf:

    volkard schrieb:

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.

    Daran ist nichts falsch und solange diese Konvention eingehalten wird, halte ich sie auch für sinnvoll. Dass Referenzen Nullzeigern vorbeugen können, bestreitet hier doch keiner und genauso unsinnig weil trivial ist eine Diskussion über strlen.


Anmelden zum Antworten