Referenzen, const ref auf ref -> Warum ist das eine Kopie und kein Fehler?



  • Hallo zusammen,

    folgendes Codebeispiel:

    using Map = std::map<int, int>;
    
      Map a;
      a.insert(std::make_pair(1, 2));
      a.insert(std::make_pair(2, 3));
      Map b;
    
      Map& aRef = a;
      Map& bRef = b;
    
      const Map& aConstRef = a;
    
      bRef = aConstRef;
    

    Unter MS VC2013 kompiliert das ohne Fehler durch.

    Ich hätte jetzt erwartet, dass er in der letzten Zeile ein Fehler meldet, das eine Const-Ref nicht auf ein Non-Const-Ref zugewiesen werden kann. Angenommen unter einer reinen Non-Const Zuweisung hätte ich erwartet, dass bRef auch eine Referenz auf a hält.

    bRef = aRef;
    

    Aus welchem Grund kompiliert er das und macht eine Kopie von a nach b?
    Oder andersherum, warum ist meine Erwartungshaltung an dieser Stelle falsch?

    Vielen Dank fürs erhellen.

    Viele Grüße,

    Jakob



  • Man kann bei Referenzen, im Gegensatz zu Pointern, nachträglich nicht mehr ändern auf welches Objekt diese verweisen. Eine Zuweisung ändert daher das Objekt wohin die Referenz gerade zeigt.



  • Noch ein Zusatz: Man kann sich Referenzen auch als Alias vorstellen:
    Man macht dem Programm ein und dasselbe Objekt unter einem weiteren Namen bekannt.
    Unter diesem Aspekt empfinde ich zumindest persönlich das Verhalten, das dich hier stutzig macht als ziemlich intuitiv.

    Gruss,
    Finnegan



  • @Finnegan
    Jo... is irgendwie schon ein bisschen ... eigen. Das mit den Referenzen.

    Bei boost::tie hab ich mir halt schon als erstes mal gedacht ... WTF?

    Wenn mans mal verstanden hat ist es natürlich logisch.
    Aber auf den 1. Blick mal recht un-intuitiv dass beim Erzeugen der Referenz was komplett anderes passiert wie wenn man danach ne Zuweisung macht.

    @__jb__

    jb schrieb:

    Angenommen unter einer reinen Non-Const Zuweisung hätte ich erwartet, dass bRef auch eine Referenz auf a hält.

    bRef = aRef;
    

    Aus welchem Grund kompiliert er das und macht eine Kopie von a nach b?
    Oder andersherum, warum ist meine Erwartungshaltung an dieser Stelle falsch?

    Weil die Regeln für Referenzen halt andere sind als du erwartet hast 😉
    Im Prinzip kannst du dir vorstellen dass ne Referenz in C++ ein Zeiger ist, bei dessen Verwendung NACH der Deklaration immer automatisch ein * davor gemacht wird.

    Dadurch kann man ja ref.x = 123; etc. mit "." schreiben statt mit "->".

    Und dann natürlich auch

    bRef = aRef;
    // entspricht
    *bPtr = *aPtr;
    

    Und dann sollte klar sein warum das Objekt geändert wird, und nicht die Referenz auf ein anderes Objekt "verbogen".

    Was sich dadurch auch klärt ist was bei sizeof(aRef) rauskommt, nämlich sizeof(A) , NICHT sizeof(A*) (mit A& aRef = someA; ).



  • Ich mag die Erklärung:

    eine Referenz ist ein Aliasnahme der Attribute (const/volatile/etc.) hinzufügen kann.



  • Vielen Dank euch!

    Mit etwas Abstand und den Erklärungen ist es mehr als einleuchtend 🙂
    Sonst würde ja auch eine Wertzuweisung (auf eine Referenz) ja gar nicht funktionieren ... ^^

    Wünsche Euch ein gelungenes Wochenende.

    Grüße

    Jakob


Anmelden zum Antworten