Frage zu const_cast



  • Hallo zusammen,

    Verstaendnisproblem bei folgenden Zeilen (Quelle: Thinking in C++, Bruce Eckel):

    [cpp]const int i = 10;
    int* j = const_cast<int*>(&i)
    [/cpp]
    

    Es heisst, nur so koenne man von const nach nonconst casten. Nur, was ist denn hier nonconst? j zeigt doch lediglich auf die Adresse der Konstanten und genau da kann man doch nichts aendern?! Was kann man also damit anfangen?



  • wollewausfander schrieb:

    genau da kann man doch nichts aendern?!

    const int i = 10;
    int* j = const_cast<int*>(&i);
    
    i = 5; // Compiler Fehler
    
    const int* p = &i;
    *p = 5; // Compiler Fehler
    
    *j = 5; // Wird wohl abstürzen, kompiliert aber anstandslos.
    


  • wollewausfander schrieb:

    [cpp]const int i = 10;
    int* j = const_cast<int*>(&i)
    [/cpp]
    

    Es heisst, nur so koenne man von const nach nonconst casten. Nur, was ist denn hier nonconst? j zeigt doch lediglich auf die Adresse der Konstanten und genau da kann man doch nichts aendern?! Was kann man also damit anfangen?

    Nein, j ist ein Zeiger auf ein int . Die Tatsache, dass der Pointee eigentlich const ist, davon weiß j nichts (für j ist i also non-const). Solltest du versuchen, dem Pointee etwas zuzuweisen, landest du bei undefiniertem Verhalten.

    Die Kenntniss zu haben, dass es so etwas gibt, ist ok, machen solltest du das aber nicht.


  • Mod

    Den const_cast benutzt du ja auch normal nicht, sondern in der Praxis eigentlich nur:
    a) um Programmierfehler (fehlende const-correctness) anderer auszugleichen. Kommt hauptsächlich vor, um C-Routinen, die fälschlicherweise einen char* erwarten, einen const char* reinzudrücken.
    b) um gewisse const/non-const-Überladungen nicht doppelt schreiben zu müssen.
    c) um volatile zu entfernen, wofür dann auch wieder a) und b) gelten

    In dem Beispiel wäre es fatal, über i zu versuchen, das j zu ändern, es demonstriert bloß die Syntax eines const_cast.



  • SeppJ schrieb:

    Den const_cast benutzt du ja auch normal nicht, sondern in der Praxis eigentlich nur:
    a) um Programmierfehler (fehlende const-correctness) anderer auszugleichen. Kommt hauptsächlich vor, um C-Routinen, die fälschlicherweise einen char* erwarten, einen const char* reinzudrücken.
    b) um gewisse const/non-const-Überladungen nicht doppelt schreiben zu müssen

    Danke erstmal allen fuer die Antworten. Hast Du fuer a) und b) je ein Beispiel? Bei a) ist mir nicht klar, was Du meinst, wenn andere Programmierfehler machen, sind die doch schon drin, man wuerde doch sowieso korrigieren, was auch ohne const_cast funktionieren wuerde, oder etwa nicht!?



  • wollewausfander schrieb:

    man wuerde doch sowieso korrigieren, was auch ohne const_cast funktionieren wuerde, oder etwa nicht!?

    Das wäre toll, aber manchmal hast du nicht die Möglichkeit das zu korrigieren. z.B. weil es eine externe Bibliothek ist oder Ähnliches.

    Zu 2)

    struct xyz
    {
      int& get()
      {
        ...;
        return ...;
      }
    
      const int& get() const
      {
        return const_cast<xyz*>(this)->get();
      }
    };
    


  • Genau falschrum cooky.


  • Mod

    Beispiel zu b:

    const int* kompliziert(const int* i) { /* kompliziertes Zeug auf i, aber nicht auf *i */ return i;}
    
    int* kompliziert(int* i) {/* Wie die const-Version aufrufen, um den Code nicht zu wiederholen? So: */ return const_cast<int*>(kompliziert(const_cast<const int*>(i)));}
    

    Oder auch umgekehrt, wenn man sich ganz sicher ist, dass die non-const-Version den Pointee nicht verändert. Dann hat man jedoch keine Garantien vom Compiler für die Richtigkeit.

    Kommt selten vor.

    edit: Zu spät. Andersrum wie cooky kann man es auch machen, wie ich schon erwähnt habe. Dann ist man eben selber verantwortlich, dafür ist der Code etwas kürzer, weil man nur einen Cast braucht.



  • Danke fuer die Antworten. Was ich jedoch nicht verstehe, was Ihr mit 'umgekehrt' meint?! Wieso ist Seppj's Code 'umgekehrt dem von 'Cookie' ?


  • Mod

    wollewausfander schrieb:

    Danke fuer die Antworten. Was ich jedoch nicht verstehe, was Ihr mit 'umgekehrt' meint?! Wieso ist Seppj's Code 'umgekehrt dem von 'Cookie' ?

    int* kompliziert(int* i) { /* kompliziertes Zeug auf i, aber nicht auf *i */ return i;}
    
    const int* kompliziert(const int* i) {/* Wie die non-const-Version aufrufen, um den Code nicht zu wiederholen? So: */ return kompliziert(const_cast<int*>(i));}
    

    Aber dann sollte man lieber sicher sein, dass das auch wirklich richtig ist.



  • Danke Seppj. Jedoch, die Frage war, was zwischen Deinem und Cookie's Code 'umgekehrt' ist. Mir faellt es ausserdem etwas schwer, den code zuzuordnen. Um was handelt es sich genau, um angepassten Code, der von 'falsch programmiertem' externen code aufgerufen wird oder umgekehrt? Wo wird denn wann was aufgerufen, und was war/ist falsch?



  • Kellerautomat schrieb:

    Genau falschrum cooky.

    Andererseits versteh ich das nicht, für sowas gibt es doch mutable .



  • Hacker schrieb:

    Andererseits versteh ich das nicht, für sowas gibt es doch mutable .

    Falsch.


  • Mod

    wollewausfander schrieb:

    Danke Seppj. Jedoch, die Frage war, was zwischen Deinem und Cookie's Code 'umgekehrt' ist. Mir faellt es ausserdem etwas schwer, den code zuzuordnen. Um was handelt es sich genau, um angepassten Code, der von 'falsch programmiertem' externen code aufgerufen wird oder umgekehrt? Wo wird denn wann was aufgerufen, und was war/ist falsch?

    Das war ein Beispiel zu meinem Punkt b, wie man in manchen Fällen Codeduplizierung sparen kann, nicht zum Aufruf von falschem externen Code. Man kann mit dem const_cast sowohl von der const-Variante aus die non-const aufrufen als auch umgekehrt. Das war das "umgekehrt" von dem wir gesprochen haben.



  • SeppJ schrieb:

    Das war ein Beispiel zu meinem Punkt b, wie man in manchen Fällen Codeduplizierung sparen kann, nicht zum Aufruf von falschem externen Code. Man kann mit dem const_cast sowohl von der const-Variante aus die non-const aufrufen als auch umgekehrt. Das war das "umgekehrt" von dem wir gesprochen haben.

    Alles klar, danke!


Anmelden zum Antworten