c++ referencen pointer best practice



  • Hi All

    Ich frage mich schon lange was den das beste ist als funktion rückgabewert bei Klassenmethoden? -> Pointer oder Referencen, dazu ein Beispiel:

    class Test {
    
    1:
    const std::string& getStr() { return str; }
    
    2:
    std::string& getStr() { return str; }
    
    3:
    std::string* getStr() { return *str; }
    
    private:
    std:string m_str;
    
    }
    

    Welche der 3 funktionen ist am bestten oder was ist best practice?

    Warum die Frage, ich bekoome bei unterem beispiel folgende Fehlermeldung:

    passing `const hxItsCatInfString' as `this' argument of `const std::string& hxItsCatInfString::GetITSParam()' discards qualifiers

    class hxItsCatInfString  {
    
    inline const std::string& GetCompSub() const {
            return  m_StrCompSub;
        };
        void SetCompSub(const std::string& str) {
            m_StrCompSub = str;
        };
    
    private:
       std::string m_StrCompSub;
    };
    
    class  hxItsCatInfChild {
    
    const hxItsCatInfString& GetCatName() const {
            return  m_CatInfDef;
    };
    
    private:
    hxItsCatInfString      m_CatInfDef;
    
    };
    

    Wenn ich nun folgendes mache gehts nicht mehr:

    int main() {
    hxItsCatInfChild test;
    std::string paramId = test.GetCatName().GetITSParam();
    }
    

    Was daran ist schlecht oder wo würdet ihr mit pointers arbeiten und wo mit const ref und wo nur mit ref????

    Vielen Dank



  • Und das entschiedende hast du nicht gepostet:
    Wie schaut

    hxItsCatInfString::GetITSParam()
    

    aus?



  • Der Fehler tritt auf, weil das Objekt this konstant ist, aber die Funktion getItsParam nicht, d. h. sie darf nur für nicht-konstante Instanzen aufgerufen werden.

    Und zu deiner best practise:

    4.
    const std::string getStr() { return str; }
    

    Denn was ist das für ein getter, über den man setten kann?



  • Michael E. schrieb:

    Und zu deiner best practise:

    4.
    const std::string getStr() { return str; }
    

    die begruendung wuerde mich aber echt mal interessieren



  • Wie schon gesagt: Die Funktion soll ein reiner Getter sein, also brauch ich auch keinen schreibenden Zugriff auf interne Daten. Störst du dich an dem Übergeben per value oder an dem const?



  • Michael E. schrieb:

    Wie schon gesagt: Wenn ich meinee Funktion ein reiner Getter sein soll, dann darf man den Klassenmember nicht verändern können. Störst du dich an dem Übergeben per value oder an dem const?

    Was spricht gegen ein string const& ?



  • Ob per reference oder per value ist mir eigentlich fast egal. Für die Referenz würde der Geschwindigkeitsvorteil sprechen, wobei ich mich davon in letzter Zeit sehr wenig beeinflussen lasse, denn man wird es bei der Programmausführung höchstwahrscheinlich eh nicht merken. Für die Wertrückgabe spricht, dass man etwas besser die Schnittstelle der Klasse von der Implementierung trennt.

    struct Foo
    {
        vector<int> bar;
    
        const vector<int> getBar() { return bar; }
    };
    

    =>

    struct Foo
    {
        list<int> bar;
    
        const vector<int> getBar() { vector<int> temp; copy(bar.begin(), bar.end(), back_inserter(temp); return temp; }
    };
    

    Wenn ich eine Referenz zurückgeben würde, müsste ich das Objekt weiterleben lassen.

    Alles sehr schwache Argumente, deshalb wäre es mir fast egal. Was hast du denn gegen meine Variante?



  • Egal ob 1 oder 4, aber die Member-Funktion sollte auf jeden Fall als 'const' deklariert sein:

    const std::string& getStr() const { return str; }
    // oder
    std::string getStr() const { return str; } // <- das const vor std::string ist aber total überflüssig (in Bezug auf Lösung4 von Michael E.)
    


  • Michael E. schrieb:

    ...Für die Wertrückgabe spricht, dass man etwas besser die Schnittstelle der Klasse von der Implementierung trennt....

    😮 😮 😮 👍 👍 😋
    Ich muss gestehen, dass ich das noch nie so begriffen habe -> jetzt aber schon.

    Man lernt eben nie aus.

    Danke,

    Simon2.



  • Th69 schrieb:

    das const vor std::string ist aber total überflüssig (in Bezug auf Lösung4 von Michael E.)

    Nein, denn durch das const wird getStr() ein reiner rvalue.



  • Michael E. schrieb:

    Nein, denn durch das const wird getStr() ein reiner rvalue.

    Der RValue wird nicht "reiner" dadurch, er ist nur const -qualifiziert. Das ist ein wichtiger Unterschied.

    Ich verweise auch gerne wieder auf eine etwas ältere Diskussion (etwas scrollen).



  • Da hast du Recht, "reiner rvalue" war definitiv der falsche Ausdruck dafür.

    Aber gemeint habe ich schon das Richtige 😉


Anmelden zum Antworten