Wann Referenzen, wann Pointer?


  • Administrator

    MrRef schrieb:

    Kann man dann sagen, dass bei C++ übergabe eines Pointers per Value nie wirklich sinnvoll ist?

    "Nie" ist viel zu streng. Aber wenn eine Referenz passt, dann nimm die Referenz. Dadurch bleiben am Ende nur noch wenige Fälle für Zeiger übrig.

    Grüssli



  • Referenz = Objekt behält immer seine Gültigkeit
    Pointer = Objekt kann NULL sein

    Beispiel:

    void print(const std::string& str); // Objekt ist immer gültig
    
    void setUserdata(UserData *data); // UserData ist optional und kann auch nicht vorhanden sein (=NULL)
    


  • volkard schrieb:

    Als Markierung, daß die Funktion den Pointee ändern kann.

    Wo ist da der Witz?



  • Also wenn ich das Objekt nicht ändere und es nicht vom integrierten Typ ist, nehme ich eine const Referenz. Wenn ich es ändere, vermeide ich auch meistens Zeiger und wähle eher die Referenz, wobei ich mir über den Ansatz der hier diskutiert wird auch schon einige Gedanken gemacht habe. Letztendlich macht es aber meines Wissens nach zumindest für den Maschienencode keinen großen Unterschied, da der Compiler bei Referenzen oft selber aber Zeiger nutzt. Jedoch könnte man wie hier schon gesagt wurde natürlich zwecks der Semantik drüber nachdenken...ich bleibe aber bei den Referenzen.

    Lg freeG



  • volkard schrieb:

    So benutze ich den Adressoperator bei Aufrufen auch. Als Markierung, daß die Funktion den Pointee ändern kann.

    Dann mach Dir ne Funktion die es kenntlich macht.

    template<typename T>
    T & this_parameter_may_be_doomed_to_be_changed_by_this_fucking_dangerous_function_or_method(T & obj){ return obj; }
    
    class doof
    {
        void warum(deshalb & d);
    };
    
    doof d;
    deshalb okay;
    
    d.warum(this_parameter_may_be_doomed_to_be_changed_by_this_fucking_dangerous_function_or_method(okay));
    

    Dann wird alles klar.



  • Denk EOutOfResources hat es schon passend ausgedrueckt.

    Referenzen wo man kann,
    Pointer wo man "muss"

    Damit reduziert sich die anwendung von Zeigern an diesen Stellen auf ein paar wenige valide Gruende:

    - Ungueltige Objekte. Nicht jedes Object kann ich in der Programmlogik so bauen, das es quasi einen ungültigkeitswert bekommt. Da referenzen immer gueltig sein muessen, könnt ich mit denen nicht signalisieren "Hallo, lass mich in ruhe, ich bin eigentlich ungueltig". Dafür bieten sich dann pointer an !

    - Kompatiblitaet zu vorherigen Code. Wenn jemand vor mir (ne Bib oder Framework) schon pointer wegen dem ungeultigkeitszeug verwendet, wuerde es unnötig komplex werden, das auf referenzen runterzubrechen.

    - Ab und an braucht man eine variable, die zur Laufzeit auf unterschiedliche Objecte Zeigt, wo das Object quasi ausgetauscht wird ... versuch das mal mit referenzen und sauberen C++ Stil 🙂

    Ciao ...



  • RHBaum schrieb:

    versuch das mal mit referenzen und sauberen C++ Stil 🙂

    Der Stil wird durch Referenzen nicht sauberer.
    Ihr überstrapaziert die Referenzen. Das ist die selbe Schiene wie das Verwenden von std::string für *alle* Zeichenketten, weil es "mehr C++" ist. Nix gut.
    Die Referenzen mußten für die Operatorenüberladung erfunden werden. Ok, jetzt haben wir sie. Aber den Haupt-Code verschlimmern sie leider. Deswegen empfiehlt Onkel Volkard: Sparsam einsetzen.

    Meine Debugsession sieht so aus:

    c=siquo(b,c);
    bar.foo(a,&b);//patsch, NUR hier kann b kaputtgegangen sein
    print(b);
    

  • Administrator

    Meine Debugsession sieht so aus:
    Ich setze einen Watchpoint auf b und lasse den Debugger die Arbeit für mich erledigen 😉

    Im übrigen hast du den Satz von RHBaum völlig aus dem Kontext gerissen. Und wieso deine Debugsession nicht unbedingt funktionieren muss, wurde auch schon aufgezeigt. Zudem hat hier überhaupt niemand empfohlen, dass man ausschliesslich Referenzen einsetzen soll. Bei std::string gilt auch, dass man ihn meistens nur in Spezialfällen durch ein char const* oder ähnliches ersetzen kann.

    Grüssli



  • Dravere schrieb:

    Meine Debugsession sieht so aus:
    Ich setze einen Watchpoint auf b und lasse den Debugger die Arbeit für mich erledigen 😉

    Kopf ist schneller als Debugger.

    Dravere schrieb:

    Im übrigen hast du den Satz von RHBaum völlig aus dem Kontext gerissen.

    Nö. Sein Konstrukt zieht die Verwendung von Referenzen und den guten C++-Stil rhetorisch in eine Nähe, die ich so nicht stehen lassen wollte.

    Dravere schrieb:

    Und wieso deine Debugsession nicht unbedingt funktionieren muss, wurde auch schon aufgezeigt.

    Kein Mittel ist erschöpfend.

    Dravere schrieb:

    Zudem hat hier überhaupt niemand empfohlen, dass man ausschliesslich Referenzen einsetzen soll.

    Doch, RHBaum war das.

    Dravere schrieb:

    Bei std::string gilt auch, dass man ihn meistens nur in Spezialfällen durch ein char const* oder ähnliches ersetzen kann.

    Stringliterale (Spezialfälle) sind char-Arrays. Ich brauche einen Grund, sie zu string zu machen.


  • Administrator

    volkard schrieb:

    Kopf ist schneller als Debugger.

    Und macht mehr Fehler, siehe auch ->

    volkard schrieb:

    Kein Mittel ist erschöpfend.

    volkard schrieb:

    Nö. Sein Konstrukt zieht die Verwendung von Referenzen und den guten C++-Stil rhetorisch in eine Nähe, die ich so nicht stehen lassen wollte.

    ... sogar wenn du damit nur Spass machst, ist es einfach nur blöd.

    volkard schrieb:

    Doch, RHBaum war das.

    Kauf dir eine Brille ...

    volkard schrieb:

    Stringliterale (Spezialfälle) sind char-Arrays. Ich brauche einen Grund, sie zu string zu machen.

    Um damit zu arbeiten?

    Das ist mir zu blöd. Wenn man keine Argumente mehr hat ...

    Grüssli



  • volkard schrieb:

    RHBaum schrieb:

    versuch das mal mit referenzen und sauberen C++ Stil 🙂

    Der Stil wird durch Referenzen nicht sauberer. Ihr überstrapaziert die Referenzen.

    Sehe ich anders. Wenn ich Zeiger übergebe ist NULL zulässig, und das ist zumindest bei den überwiegenden Fall in den Programmen, eher die Ausnahme als die Regel. Einer Referenz sieht man an, das ein Wert erwartet wird, einem Zeiger nicht. Einen Zeiger muss man zudem eigentlich immer vor der Verwendung prüfen. Ich glaube daher schon, das Referenzen immer Zeigern vorzuziehen sind, wenn man letztere nicht benötigt.

    volkard schrieb:

    Das ist die selbe Schiene wie das Verwenden von std::string für *alle* Zeichenketten, weil es "mehr C++" ist. Nix gut.

    Ich sehe in der überwiegenden Mehrzahl keine Gründe die für char-Arrays gegenüber (einer wie auch immer gearteten) Stringklasse sprechen.



  • volkard schrieb:

    Aber den Haupt-Code verschlimmern sie leider.

    Warum? Nur weil du nicht von außen siehst wo eine Variable geändert wird?



  • IntelliSense zeigt das doch an.



  • EOutOfResources schrieb:

    IntelliSense zeigt das doch an.

    Nicht jeder hat IntelliSense 😉



  • wwwwwwwwwww schrieb:

    volkard schrieb:

    Aber den Haupt-Code verschlimmern sie leider.

    Warum? Nur weil du nicht von außen siehst wo eine Variable geändert wird?

    Das siehst du aber auch keinen Zeiger an.



  • asc schrieb:

    wwwwwwwwwww schrieb:

    volkard schrieb:

    Aber den Haupt-Code verschlimmern sie leider.

    Warum? Nur weil du nicht von außen siehst wo eine Variable geändert wird?

    Das siehst du aber auch keinen Zeiger an.

    Volkard benutzt bestimmt nur dort Zeiger, wo die Parameter auch geändert werden. Sehr diszipliniert. Respekt. :p



  • volkard schrieb:

    Der Stil wird durch Referenzen nicht sauberer.
    Ihr überstrapaziert die Referenzen. Das ist die selbe Schiene wie das Verwenden von std::string für *alle* Zeichenketten, weil es "mehr C++" ist. Nix gut.
    Die Referenzen mußten für die Operatorenüberladung erfunden werden. Ok, jetzt haben wir sie. Aber den Haupt-Code verschlimmern sie leider. Deswegen empfiehlt Onkel Volkard: Sparsam einsetzen.

    Wow! Ich hätte dir niemals derart liberales Gedankengut zugetraut... 😃
    Und insbesondere die indirekte Verherrlichung von char-Arrays... also pfui! Und sowas in einem C++-Forum, wo der STL-Monotheismus exzessiv praktiziert und propagiert wird! 😃

    Im Übrigen halte ich es so wie einige andere auch.

    Wann immer es geht übergebe ich per Referenz wenn möglich auch const. Wo es NULL sein darf, auch mal Pointer... Ich bin also flexibel in der Anwendung 🙂



  • asc schrieb:

    Das siehst du aber auch keinem Zeiger an.

    Aber manch einer erwartet es bei einem Pointer vielleicht eher.
    Du vielleicht nicht, ich auch nicht, aber andere schon.



  • Meiner Meinung nach ist der Punkt der:
    Wenn ich einen Pointer übergebe, dann weiß ich, daß das Objekt, auf das gezeigt wird, geändert werden kann, ohne dass ich mir die Deklaration/Definition der aufgerufenen Funktion ansehen muss.
    Wenn ich ein Objekt übergebe, dann sehe ich an der Aufrufstelle nicht, ob die aufgerufene Funktion das als Objekt oder als Referenz nimmt. Bei der Entwicklung ist mir das noch relativ egal, wenn ich aber nach längerer Zeit den Quellcode ansehen muss, dann finde ich es hilfreich, wenn ich mich darauf verlassen kann, dass ein übergebenes Objekt nach Rückkehr noch genau so aussieht wie vor dem Aufruf. Deshalb halte ich es grundsätzlich wie Volkard:
    Pointer, wenn die Funktion den Paramter ändert, anderenfalls konstante Referenzen.



  • Ihr tut immer alle rum von wegen Intellisense, Intellisense, Intellisense und seid dann nicht in der Lage, euch den Funktionskopf der auzurufenden Funktion, der ja meist automatisch eingeblendet wird, anzugucken? ohje...

    Meist erkennt man ja schon im Funktionkopf an der Referenz, dem Pointer, oder der const Referenz, ob das Objekt möglicherweise in der Funktion geändert wird, oder nicht geändert wird.


Anmelden zum Antworten