Rückgabewert: Referenz oder nicht?



  • Hi ihr!

    Nachdem ich ein paar mal dachte ich wüsste es jetzt und dann ein paar mal doch wieder unsicher war und hin und her:

    Wann sollte ich eine Funktion eine Referenz zurückgeben lassen, und wann lass ich das besser sein? Und, damit ichs vielleicht endlich mal verstehe: warum (nicht)?
    Ich meine dabei z.B. sowas:

    class Person
    {
    /*...*/
    public: 
    std::string & getName();
    /*...*/
    };
    

    Wäre echt dankbar wenn ich das irgendwann mal verstehen würde.. Ist so ein Einhorn von mir...



  • MeinBenutzername schrieb:

    Wann sollte ich eine Funktion eine Referenz zurückgeben lassen, und wann lass ich das besser sein? Und, damit ichs vielleicht endlich mal verstehe: warum (nicht)?

    Grundsätzlich wenn du dir diese Frage stellts, bitte auch const-Referenzen beachten...

    Wenn du eine nicht-konstante Referenz zurückgibst, solltest du bedenken, das man den Wert direkt manipulieren kann (Und damit die Datenkapselung einer Klasse umgeht). Ich bezweifel das du dies wirklich willst - Den dann braucht man auch keine Setter mehr - und kann die Modifikation eines Wertes nicht kontrollieren.

    In der Regel sind nicht-konstante Referenzen als Rückgabe nur sinnvoll, wenn man definitiv die Manipulation zulässt. Ein Beispiel davon sind die Streamoperatoren bei den iostreams (Dort ist das erste Argument eine Referenz auf den Stream, der auch wieder zurückgegeben wird, um die Streamoperatoren koppeln zu können). Ich würde sagen in der Regel ist dies der Sonderfall, nicht die Regel.

    Konstante Referenzen würde ich dann als Rückgabe von Membervariablen erwarten wenn große Datenmengen übertragen werden sollen (z.B. Vektoren), und damit die Optimierung durch den Compiler unwahrscheinlich ist (Im Hinterkopf aber die Fallstricke beachtest: Wenn sich der Wert der Membervariable ändert...).

    Wertrückgaben verwende ich eigentlich in 98% der Fälle (Der Compiler kann unnötige Kopien häufig wegoptimieren).

    cu André



  • MeinBenutzername schrieb:

    Hi ihr!

    Nachdem ich ein paar mal dachte ich wüsste es jetzt und dann ein paar mal doch wieder unsicher war und hin und her:

    Wann sollte ich eine Funktion eine Referenz zurückgeben lassen, und wann lass ich das besser sein? Und, damit ichs vielleicht endlich mal verstehe: warum (nicht)?
    Ich meine dabei z.B. sowas:

    class Person
    {
    /*...*/
    public: 
    std::string & getName();
    /*...*/
    };
    

    Wäre echt dankbar wenn ich das irgendwann mal verstehen würde.. Ist so ein Einhorn von mir...

    Genau sowas solltest du nach Möglichkeit NICHT machen. Damit gibst du nämlich eine Referenz auf Interna deiner Klasse, die dann von außen nach belieben verändert werden können. Wenn diese Interna verändert werden sollen, mach das über eine Setter-Methode

    void setName(std::string const& neuerName);
    

    für die Getter gibts zwei Möglichkeiten:

    std::string getName() const;
    std::string const& getName() const;
    

    Die erste Möglichkeit kopiert den internen String, ist also aufwändiger. dafür kann die Rückgabe dann direkt modifiziert werden.
    Die zweite Möglichkeit verzichtet auf die Kopie, dafür kann das Ergebnis weder direkt modifiziert noch an einen nichtkonstanten Referenzparameter einer anderen Funktion gebunden werden.
    In den meisten Fällen ist die zweite Version vorzuziehen, da bei Bedarf das Kopieren nachgeholt werden kann und die Modifikationen dann an der Kopie durchgeführt werden können. Es entsteht also kein Nachteil, während bei Version 1 immer die Kopie gemacht wird, auch wenn das vielleicht garnicht nötig ist.



  • Dankeschön, ich glaub es hat Klick gemacht 🙂



  • bei (const) referenzen musst du dann nur darauf achten, dass so etwas nicht mehr geht:

    const std::string& ClassASD::GetName() const
    {
     return this->bla + ".txt";
    } //achtung undefiniert, da bla+".txt" hier zerstört wird!
    

    sondern du hier den string per value zurückgeben musst... so bald es aber möglich ist, solltest du es auch nutzen (außer bei PODs und idR beim operator[]) ^^

    bb



  • asc schrieb:

    [...] nicht-konstante Referenz [...]

    Konstante Referenzen [...]

    Tut mir leid, wenn ich so ein Detail kommentiere, aber das kann von Anfängern (für die Referenzen und Zeiger meist eh nicht trivial sind) schnell falsch aufgefasst werden.

    Referenzen sind per Definition konstant, können während ihrer Lebensdauer also nicht auf verschiedene Objekte verweisen und müssen bei ihrer Definition initialisiert werden. Das const sagt nur etwas über den referenzierten Typen aus - genauer, ob dieser über die Referenz geändert werden darf.

    Aus dem Grund verwende ich selber eigentlich immer die Begriffe "Const-Referenz" und "Non-Const-Referenz". Diese sind zwar auch nicht immer ganz eindeutig, aber meiner Ansicht weniger irreführend. 🙂



  • Ich merk mir das so:

    Referenz ~ dereferenzierter konstanter Zeiger auf irgend was. Muss natuerlich initialisiert werden, weil was konstantes, nicht veraenderbares was einen undefinierten Wert hat, macht ja kein sinn,

    ergo
    konstante referenz = dereferenzierter konstanter Zeiger auf einen konstanten (nicht veraenderlichen) Wert.

    Der C++ Begriff "Referenz" hat also technisch das erste konstant schon eingebaut IMHO. Aber mit der Zeit wenn man da mal durchgestiegen ist ... ist es nicht mehr so verwirrend ...

    Ciao ...



  • RHBaum schrieb:

    Der C++ Begriff "Referenz" hat also technisch das erste konstant schon eingebaut IMHO.

    Von konstanten Referenzen zu sprechen, ist aus diesem Grunde auch redundant.

    RHBaum schrieb:

    Aber mit der Zeit wenn man da mal durchgestiegen ist ... ist es nicht mehr so verwirrend ...

    Unter der Voraussetzung, dass man alles verstanden hat und weiss, dass Referenzen immer konstant sind, vielleicht. Aber trotzdem finde ich es besser, man achtet sich ein wenig auf die Begrifflichkeiten. Nicht nur, weil es Anfänger weniger verwirrt, sondern weil der Ausdruck "nicht-konstante Referenz" an sich einfach falsch ist.



  • Nexus schrieb:

    Nicht nur, weil es Anfänger weniger verwirrt, sondern weil der Ausdruck "nicht-konstante Referenz" an sich einfach falsch ist.

    Akzeptiert - auch wenn ich diese Begriffe durchaus als gebräuchlich aus mind. 2 Unternehmen kenne (Zudem so auch in deutschen Büchern verwendet wird, wie eine google-Suche erbracht hat).

    Dann wäre ich dennoch dafür das man einen möglichst kurzen Begriff oder Ausdruck im Deutschen findet.

    P.S: Mal ein kurzer Auszug der Bücher im deutschen die "nicht konstante Referenz" als Begriff verwenden:

    • C++: der Einstieg in die Programmierung (Ulrich Eisenecker)
    • Objektorientiertes Programmieren in C++ (Nicolai Josuttis)
    • Effektiv C++ Programmieren (Scott Meyers, Michael Tamm)
    • C++ GUI Programmierung mit QT 4: Die offizielle Einführung (Jasmin Blanchette, Mark Summerfield)
    • Die C++-standardbibliothek: Einführung und Nachschlagewerk (Stefan Kuhlins, Martin Schader)
    • Die C++-Programmiersprache (Bjarne Stroustrup, Nicolai Josuttis, Achim Lörke)
    • C++ Primer (Stanley B. Lippman, Josée Lajoie, Barbara E Moo)


  • asc schrieb:

    Akzeptiert - auch wenn ich diese Begriffe durchaus als gebräuchlich aus mind. 2 Unternehmen kenne (Zudem so auch in deutschen Büchern verwendet wird, wie eine google-Suche erbracht hat).

    Leider breiten sich falsche Begriffe schnell aus, wahrscheinlich weil sie hier die einfachste Möglichkeit darstellen. Zudem kann "non-const-reference" schnell mal zu "nicht konstanter Referenz" übersetzt werden...
    Aber gut, dass du das einsiehst. 🙂

    asc schrieb:

    Dann wäre ich dennoch dafür das man einen möglichst kurzen Begriff oder Ausdruck im Deutschen findet.

    Deutsch könnte schwierig werden. Aber für viele Dinge in der Informatik gibt es englische Ausdrücke oder Abkürzungen, die sehr gebräuchlich sind. Der beste, aber leider auch nicht ganz optimale Begriff scheint für mich immer noch "(Non-)Const-Referenz" (oder evtl. "-Reference"). Im Zweifelsfalle halt umschreiben...



  • Nexus schrieb:

    Aber gut, dass du das einsiehst. 🙂

    Dennoch werde ich die Begrifflichkeit nicht ändern, wenn ich nicht eine sinnvolle Entsprechung finde. Es gibt im deutschen einige Begriffe die nicht 100% passend sind, im Sprachgebrauch dennoch so verwendet werden.



  • asc schrieb:

    Es gibt im deutschen einige Begriffe die nicht 100% passend sind, im Sprachgebrauch dennoch so verwendet werden.

    Ah, das reicht natürlich bei Weitem als Rechtfertigung, selber Begriffe falsch zu verwenden. :p

    Nein, ich kann deine Haltung schon nachvollziehen, auch wenn ich sie persönlich nicht gut finde. Du hättest den ersten Schritt gegen nicht-konstante Referenzen machen können, aber nun gut... 😃



  • Nexus schrieb:

    asc schrieb:

    Es gibt im deutschen einige Begriffe die nicht 100% passend sind, im Sprachgebrauch dennoch so verwendet werden.

    Ah, das reicht natürlich bei Weitem als Rechtfertigung, selber Begriffe falsch zu verwenden. :p

    Dann steck aber bitte nie deine Kinder in den Kindergarten.

    Nexus schrieb:

    Nein, ich kann deine Haltung schon nachvollziehen, auch wenn ich sie persönlich nicht gut finde. Du hättest den ersten Schritt gegen nicht-konstante Referenzen machen können, aber nun gut... 😃

    Es gibt einen Grund warum ich das nur ablegen werde, wenn ich eine sinnvolle und relativ kurze Ersetzung bekomme:

    a) Ich mische ungern verschiedene Sprachen miteinander, das bringt den Lesefluss durcheinander (Ausnahmen sind solche Begriffe die sich tatsächlich durchgesetzt haben).

    b) Der Begriff wird von sehr viel Literatur verwendet, ich kenne ihn auch nur so. Ich behaupte auch mal das 95% der C++ Programmierer die Referenzen und const-correctness (in Kurzform kenne ich hier tatsächlich nur den englischen Begriff im üblichen Sprachgebrauch) kennen, dies auch verstehen.

    cu André


Anmelden zum Antworten