const



  • kann mir mal bitte jemand den genauen unterschied zwischen den beiden folgenden deklarationen erklären?

    //t beliebige klasse
    t const var_t_const;
    const t var_const_t;
    

    was mich auch interessiert, wo der unterschied in den zugriffs-/änderungsmöglichkeiten der variablen var_t_const bzw var_const_t liegt, falls es welche gibt.
    Desweiteren interessiert mich noch, wenn zum Beispiel bei Funktionen Referenzen oder Pointer dieser Art übergeben werden, was man damit dann machen darf und was nicht.

    void foo_const_t_r(const t &p);
    void foo_t_const_r(t const &p);
    void foo_const_t_p(const t *p);
    void foo_t_const_p(t const *p);
    


  • Zwischen den beiden Schreibweisen gibt es keinen semantischen Unterschied.

    Und bei der Übergabe von konstanten Referenzen oder Zeigern kann man die Inhalte nicht verändern, d.h. nur lesen.
    Ansonsten unterscheidet sich innerhalb der Funktion nur die Syntax, d.h. Punkt-Operator (.) oder Zeiger-Operator ( -> bzw. (*x). ).

    Und Zeiger können auf nichts zeigen (Nullzeiger: 0), während hinter einer Referenz immer ein Objekt steht.



  • Th schrieb:

    Zwischen den beiden Schreibweisen gibt es keinen semantischen Unterschied.

    Und bei der Übergabe von konstanten Referenzen oder Zeigern kann man die Inhalte nicht verändern, d.h. nur lesen.
    Ansonsten unterscheidet sich innerhalb der Funktion nur die Syntax, d.h. Punkt-Operator (.) oder Zeiger-Operator ( -> bzw. (*x). ).

    Und Zeiger können auf nichts zeigen (Nullzeiger: 0), während hinter einer Referenz immer ein Objekt steht.

    Das sehe ich zumindest bei Zeigern etwas anders.
    Da besteht meines Wissens nach ein Unterschied.

    Beispiel

    const int x;       // ok
    x = 2;             // illegal
    
    const int* x;     
    *x = 3;            // illegal
    x = &y;            // ok
    
    int* const x;
    *x = 4;            // ok
    x = &y;            // illegal
    
    const int* const x;        
    *x = 5;            // illegal
    x = &y;            // illegal
    


  • 1. Bei dem Beispiel...

    void foo_const_t_r(const t &p);
    void foo_t_const_r(t const &p);
    void foo_const_t_p(const t *p);
    void foo_t_const_p(t const *p);

    ...ist kein Unterschied zwischen den Zeigern/Referenzen.

    2. @Thrille

    const int x; // nicht ok, weil Initialisierung fehlt

    MfG



  • Trille schrieb:

    Das sehe ich zumindest bei Zeigern etwas anders.
    Da besteht meines Wissens nach ein Unterschied.

    Beispiel

    const int x;       // ok
    x = 2;             // illegal
    
    const int* x;     
    *x = 3;            // illegal
    x = &y;            // ok
    
    int* const x;
    *x = 4;            // ok
    x = &y;            // illegal
    
    const int* const x;        
    *x = 5;            // illegal
    x = &y;            // illegal
    

    ja, aber du stellst das const auch nach das sternchen 😉
    das äquivalent, das gleichbedeutend wäre zu

    const int* x;
    

    lautet

    int const* x;
    

    letztere schreibweise wird oft bevorzugt, weil man sie besser "lesen" kann, nämlich von rechts nach links:

    int const * const x; //konstanter (const) zeiger auf (*) konstante (const) ganzzahl (int)
    


  • ich denke ich habs jetzt verstanden, danke.



  • queer_boy schrieb:

    int const * const x; //konstanter (const) zeiger auf (*) konstante (const) ganzzahl (int)
    

    Man kanns auch von links nach rechts lesen:
    "Die Integer-Konstanten-Zeiger-Konstante x". 🙂



  • Das ist alles einfach nur schrecklich und hat zur Abneigung gegen Zeiger geführt. 👎 :xmas1: :xmas2:

    Kann das jemand zur Vollständigkeit auch für C++ und Referenzen aufzeigen?



  • Da gibt es nicht viel aufzuzeigen: Da Referenzen nicht "veränderbar" sind, darf rechts vom & kein const stehen. Der Rest gilt wie oben 😉



  • Das ist alles einfach nur schrecklich und hat zur Abneigung gegen Zeiger geführt

    Nope, das ist alles ganz einfach 🙂 🙂 🙂

    Kompliziert wird es wenns um Funktionszeiger geht. Und wenn die Funktion dann nochmal Funktionszeiger als Parameter nimmt... aber sowas braucht man ja kaum, und kann man meist schön mit typedef umgehen.



  • Allgemeine Regel:

    1. Beginnend beim Bezeichner

    2. Steht rechts () oder [], dann ist dies zu interpretieren
    3. Ansonsten wird links der Stern, falls vorhanden, interpretiert

    4. Zuletzt wird der Grundtyp ausgewertet.

    Dabei wird 2. und 3. so oft wiederholt, bis alles aufgelöst ist.

    char *(*(*funcptr)())[]
    

    1. funcptr ist ein
    2. Zeiger auf
    3. eine Funktion mit dem Returntyp
    4. Zeiger auf
    5. einen Vektor mit Elementen vom Typ
    6. Zeiger auf
    7. char

    MfG


Anmelden zum Antworten