const Referenz als Rückgabewert --> Verwirrung



  • Hallo,
    ich beschäftige mich gerade mit Referenzen. Wenn ich nun eine Funktion erstelle, die mir eine const Referenz zurückgibt, dann frage ich mich, wo sich dieses const bemerkbar macht oder anders gesagt: Wo liegt der Unterschied, wenn ich das const weglasse.

    Wenn ich beispielsweise const string& zurückgebe und einem String den Rückgabewert zuweise, dann kann ich diesen ja trotzdem ändern?!

    Könnt ihr mir helfen 🙄

    lg, freakC++



  • std::string str = obj.getString()  # str wird per Kopierkonstruktor mit dem ret-val erstellt
    std::string& strRef = obj.getString()
    

    Letzteres gibt einen Fehler, wenn getString() einen const-ref zurück gibt. bei einem non-const-ref verweist strRef direkt auf nen private member deiner Klasse, und ist böse, weil keine Kapselung mehr. Du könntest sonst auch den Member gleich public deklarieren.
    Also wenn Referenz zurückgeben, dann const.



  • freakC++ schrieb:

    ich beschäftige mich gerade mit Referenzen. Wenn ich nun eine Funktion erstelle, die mir eine const Referenz zurückgibt,

    Zeig mal ein Beispiel.

    freakC++ schrieb:

    dann frage ich mich, wo sich dieses const bemerkbar macht oder anders gesagt: Wo liegt der Unterschied, wenn ich das const weglasse.

    Wenn Du das const weglässt, kann man das string-Objekt über die Referenz ohne einen const_cast logisch verändern.

    freakC++ schrieb:

    Wenn ich beispielsweise const string& zurückgebe und einem String den Rückgabewert zuweise, dann kann ich diesen ja trotzdem ändern?!

    Klar. Warum nicht?

    Welches C++ Buch benutzt Du, was const und Referenzen nicht richtig erklärt?

    Gruß,
    SP



  • Hallo,
    hier kommt ein Beispiel:

    const string& strToUpper(const string& s1)
    {
    	static string s2 = "";
    	for (int i = 0; i < s1.length(); ++i)
    		s2 += toupper(s1[i]);
    	return s2;
    }
    

    Diese Funktion stellt einen String in Großbuchstaben dar. Nun kann man genauso gut das const verglassen. Da ich "const_cast" noch nicht kenne, verstehe ich nicht, welchen Sinn const als Rückgabewert hat.
    1.) Was kann hier nicht verändert werden?

    Wenn ich als Parameter einen String direkt übergebe (also z.B. so: "Hallo") und diese als Referenz haben möchte, dann muss ich diese als const deklarieren, da man ja "Hallo" über die Referenz ändern könnte, doch "Hallo" ist ja schon was konstantes.
    2.) Liege ich da richtig?

    Vielen Dank
    lg, freakC++



  • freakC++ schrieb:

    Hallo,
    hier kommt ein Beispiel:

    const string& strToUpper(const string& s1)
    {
    	static string s2 = "";
    	for (int i = 0; i < s1.length(); ++i)
    		s2 += toupper(s1[i]);
    	return s2;
    }
    

    Diese Funktion stellt einen String in Großbuchstaben dar. Nun kann man genauso gut das const verglassen. Da ich "const_cast" noch nicht kenne, verstehe ich nicht, welchen Sinn const als Rückgabewert hat.
    1.) Was kann hier nicht verändert werden?

    Der Rückgabewert.
    Beispiel:

    string benutzername=foo::bar.theConnection().createLockingHandle()->readUserName();
    if(strToUpper(username)="Adolf Hitler")
       throw PoliticalCorrectnessException();
    cout<<"neuer user: "<<benutzername<<'\n';
    registerUser(benutzername);
    

    Du siehst natürlich sofort den Fehler, und warum das const aus der Warning einen leckeren Compilerfehler macht.



  • freakC++ schrieb:

    1.) Was kann hier nicht verändert werden?

    s2 kann nicht von außen verändert werden, weil du eine const-Referenz darauf zurückgibst. Weist du den Rückgabewert einem anderen String zu, wird s2 kopiert.

    2.) Liege ich da richtig?

    Wenn es ein std::string ist, dann nein. Wenn du ein String-Literal übergibst, wird ein std::string -Objekt automatisch erzeugt, weil std::string einen passenden Konstruktor hat. Dieses Objekt ist nur lokal gültig, das Literal wird nicht angefasst.

    Deine Funktion ist übrigens buggy, weil du s2 niemals leerst.



  • Registrierter Troll schrieb:

    Deine Funktion ist übrigens buggy, weil du s2 niemals leerst.

    Die Funktion kommt mir sowieso vor, als würde man mit static und Const-Referenz-Rückgabe versuchen, Rechenzeit zu sparen. Mit RVO ist das in vielen Fällen nicht mehr nötig, dann macht man es lieber auf die intuitive Art (in der Funktion neuen String erstellen und Kopie zurückgeben).

    Alternativ kann man auch eine In-Place-Funktion void ToUpper(std::string& Str); schreiben, in der man gleich auf dem übergebenen Objekt arbeitet. Dann kann man die obere Kopierfunktion mittels dieser implementieren - analog zur üblichen Definition von operator+= und operator+ .



  • Angenommen ich deklariere den Rückgabewert nicht als const...kann mir jemand mal ein Beispiel zeigen, wie ich dann s2 von außerhalb ändern kann?

    Vielen Dank für die anderen Beispiele.
    lg, freakC++



  • freakC++ schrieb:

    Angenommen ich deklariere den Rückgabewert nicht als const...kann mir jemand mal ein Beispiel zeigen, wie ich dann s2 von außerhalb ändern kann?

    Wie wärs, wenn du mal selbst etwas ausprobierst, statt jedes kleine Detail nachzufragen?

    std::string s;
    strToUpper(s) = "nein!";
    


  • freakC++ schrieb:

    Angenommen ich deklariere den Rückgabewert nicht als const...kann mir jemand mal ein Beispiel zeigen, wie ich dann s2 von außerhalb ändern kann?

    Habe ich schon gemacht.



  • Ahh..natürlich! Danke! Vielen Dank!

    lg, freakC++


Anmelden zum Antworten