Unterschied zwischen ref und zeiger



  • Hi,

    naben Erhards Quellcode noch ein bischen "Freitext" (der aber in nichts dem Code widerspricht)

    muhi schrieb:

    Hallo Leute,
    ...
    ich würde gerne wissen was der Unterschied zwischen einer ref var ist und einem zeiger (in der anwendung)
    ...

    Ganz kurz:
    - "Zeiger sind variable und 'nullfähige' Referenzen"; man kann dieselbe Zeigervariable mal auf das eine und später auf das andere Objekt zeigen lassen und auf 0 setzen. Mit Referenzen geht das nicht.
    - Man sagt (habe das nicht selbst überprüft), dass viele Compiler intern Referenzen über (const-)Zeiger abbilden.
    - Das, was in Java "Referenz" heißt, heißt in C++ "Zeiger".

    muhi schrieb:

    Hallo Leute,
    ...wird bei zeigern auch die adresse/der var wert (je nachdem ob adresszeichen "&" oder nur zeiger) überschrieben?
    ...

    Ich weiß nicht genau, ob wir dasselbe meinen, aber:
    - Bei der Zeigerdeklaration kannst Du entscheiden, ob das Objekt, auf das er zeigt, verändern willst oder nicht. ("const" an der richtigen Stelle).
    - Dasselbe gilt auch für eine Referenz.
    - ABER: Syntaktisch sieht der Zugriff über einen Zeiger anders aus ("ptr->element"; "ref.element"); syntaktisch sieht der zugriff via Referenz genauso aus wie der "Zugriff über das Objekt selbst"
    - Deswegen kann man eine Referenz auch als "Alias für ein Objekt" nennen.

    A a; // erzeugt ein A-Objekt, auf das man üner den Variablennamen a zugreifen kann
    A& a_ref = a; // erzeugt eine Referenz auf ein A-Objekt und lässt sie auf das eben erzeugte Objekt zeigen
    a.element = 1; // jetzt hat a.element den Wert 1
    a_ref.element = 2; // jetzt hat a.element den Wert 2; a !!!!
    

    Gruß,

    Simon2.



  • - Man sagt (habe das nicht selbst überprüft), dass viele Compiler intern Referenzen über (const-)Zeiger abbilden.

    So ist es auch, es gibt ja sonst keine Möglichkeit. Eine Referenz ist intern ein Zeiger, nur dass der Compiler das Dereferenzieren für einen übernimmt.

    - Deswegen kann man eine Referenz auch als "Alias für ein Objekt" nennen.

    ....was wiederum bedeutet, dass eine Referenz keinen eigenen Speicher belegt und daher nicht selber referenziert werden kann.

    - Bei der Zeigerdeklaration kannst Du entscheiden, ob das Objekt, auf das er zeigt, verändern willst oder nicht. ("const" an der richtigen Stelle).
    - Dasselbe gilt auch für eine Referenz.

    Nicht ganz, während bei Zeigern das gilt:

    int j = 578;
    
    int *p = &j;  //Variabler Zeiger, variables Objekt
    
    const int *p2 = &j;  //Variabler Zeiger, konstantes Objekt
    //int const *p2 = &j;  //ebenso: Variabler Zeiger, konstantes Objekt
    
    int * const p3 = &j; //Konstanter Zeiger, variables Objekt
    
    const int * const p4 = &j;  //Konstanter Zeiger, konstantes Objekt
    

    Ist bei Referenzen nur folgendes in Ordnung:

    int j = 578;
    
    int &ref = j;  //normale Referenz
    
    const int &ref = j;  //konstante Referenz
    
    int const &ref = j;  //ebenso
    

    Das ist ill-formed:

    int & const ref = j;
    

    MfG

    GPC



  • GPC schrieb:

    ...
    Das ist ill-formed:

    int & const ref = j;
    

    ...

    Da man eine Referenz sowieso nicht "umhängen" kann (was ich druchaus erwähnt habe), wäre das auch sinnlos. 😉
    Letztlich sehe ich nicht, was an meiner Aussage falsch/irreführend war - zumal es nicht um "* const" ging, sondern um die Frage, der Veränderung eines Objektes.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    GPC schrieb:

    ...
    Das ist ill-formed:

    int & const ref = j;
    

    ...

    Da man eine Referenz sowieso nicht "umhängen" kann (was ich druchaus erwähnt habe), wäre das auch sinnlos. 😉
    Letztlich sehe ich nicht, was an meiner Aussage falsch/irreführend war - zumal es nicht um "* const" ging, sondern um die Frage, der Veränderung eines Objektes.

    Sie war nicht generell falsch, ich bezog mich auf das " "const" an der richtigen Stelle " und den Satz drunter "Dasselbe gilt auch für eine Referenz". Und genau das selbe gilt eben nicht, aber egal. Schwamm drüber 🙂

    MfG

    GPC



  • GPC schrieb:

    ...Und genau das selbe gilt eben nicht, aber egal. ...

    Simon2 schrieb:

    ...
    - Bei der Zeigerdeklaration kannst Du entscheiden, ob das Objekt, auf das er zeigt, verändern willst oder nicht. ("const" an der richtigen Stelle).
    - Dasselbe gilt auch für eine Referenz.
    ...

    😕
    Die Aussage: "Setzt man bei der Deklaration ein const an der richtigen Stelle, kann man den verändernden Zugriff auf das referenzierte Objekt verhindern" gilt doch für Referenzen exakt so wie für Zeiger, oder ? Es ist "dasselbe".
    Ich habe auch nie behauptet, dass man nicht ein const irgendwohin schreiben kann und immer klappt alles oder so ....

    Gruß,

    Simon2.



  • Simon2 schrieb:

    GPC schrieb:

    ...Und genau das selbe gilt eben nicht, aber egal. ...

    Simon2 schrieb:

    ...
    - Bei der Zeigerdeklaration kannst Du entscheiden, ob das Objekt, auf das er zeigt, verändern willst oder nicht. ("const" an der richtigen Stelle).
    - Dasselbe gilt auch für eine Referenz.
    ...

    😕
    Die Aussage: "Setzt man bei der Deklaration ein const an der richtigen Stelle, kann man den verändernden Zugriff auf das referenzierte Objekt verhindern" gilt doch für Referenzen exakt so wie für Zeiger, oder ? Es ist "dasselbe".

    Ja, wenn man es nur so betrachtet schon:

    int j=578;
    const int *p = &j;
    const int &r = j;
    

    Grüße

    GPC



  • Hallo Leute, also erst Mal danke für die Antworten:
    Leider kenn ich mich noch nicht ganz so aus.

    Ich weiss ganz genau was eine ref variable ist und wozu sie gut ist.
    Ich weiss auch was ein Zeiger ist und wozu er gut ist.

    Bei Zeigern jedoch blick ich zu wenig dahinter/weiss eines nicht ganz genau:

    Hier meine konkreten Fragen:

    Welche arithmetischen Operationen kann man mit Zeigern ausführen?
    Wenn ich den Wert des Zeigers ändere, ändert sich dann auch der Wert der Variable oder ist der zeiger hier eigentsändiger?

    Bei Zeigern kann ich ja mit dem "&" operator (?) auf die Adresse verweisen und sonst auf die variable.

    Wo ist hier der nutzen, dass man beides kann?

    Wo ist der genaue Nutzen(vorteil) von refs gegenüber zeigern??

    Vielen Dank



  • Spontan fällt mir da z.B. ein, das man keine Nullreferenzen haben kann. Du kannst somit also Situationen erzwingen, in dem etwas da sein muss und nicht wie bei den Zeigen kann.

    Mehr und besser folgt sicherlich gleich 🙂





  • muhi schrieb:

    Hallo Leute, also erst Mal danke für die Antworten:
    ...
    Hier meine konkreten Fragen:
    Welche arithmetischen Operationen kann man mit Zeigern ausführen?
    ....

    Du solltest andersherum vorgehen: Was willst Du machen ?
    Stell' Dir einen Pointer wie Deine Hausnummer vor: Das ist einerseits einfach nur eine Zahl (vgl. int), aber welchen Sinn machen "arithmetische Operationen" auf Deine Hausnummer ? Welchen Sinn bringt es, zwei Hausnummern zu multiplizieren ? ...

    muhi schrieb:

    ...Wenn ich den Wert des Zeigers ändere, ändert sich dann auch der Wert der Variable oder ist der zeiger hier eigentsändiger? ...

    Wenn Du die Hausnummer "hast" (= Zeiger dereferenzierst ... mit * oder ->), kannst Du das entsprechende Haus betreten, abreißen, .... was immer das Haus gerade kann, auf das die Hausnummer verweist.
    Wenn Du die Hausnummer (= Wert der Zeigervariable) änderst, verweist Du auf ein anderes Haus (= Objekt)... hast mit diesem "Umschwenken" aber weder am alten noch am neuen Haus etwas geändert.

    muhi schrieb:

    Bei Zeigern kann ich ja mit dem "&" operator (?) auf die Adresse verweisen und sonst auf die variable.

    Da hast Du etwas mißverstanden:
    - "referenzieren" ("&") bedeutet: "Gib mir die Adresse von diesem Objekt" - das macht nur auf Objekte (damit schließe ich primitive Datentypen mit ein - geht mir nur um den Gegensatz zwiscehn Objekt und Zeiger) Sinn ("Du lässt Dir soz. die Hausnummer geben.")
    - "dereferenzieren" ("*" oder "->") bedeutet dagegen, dass Du "das Haus zur Nummer bekommst" .... also aus einem Zeiger das Objekt, auf das er gerade zeigt.

    Tricky wird's wenn man bedenkt, dass auch der Wert der Zeigervariable irgendwo im Speicher steht .... damit kann man dann auch die Adresse dieser Zeigervariablen herausbekommen (soz. "die Hausnummer des Zettels, auf dem die Hausnummer steht" ;)) .... aber hier kommen wir an die Grenze der Analogie.

    muhi schrieb:

    Wo ist der genaue Nutzen(vorteil) von refs gegenüber zeigern??
    Vielen Dank

    Eine Referenz sagt einfach was Anderes aus: Sie hat selbst keine Adresse und MUSS auf etwas zeigen (dass man eine Referenz auch ungültig machen kann, weiß ich auch ... darum geht's hier aber nicht".
    Auch hier wird andersherum ein Schuh draus: Mit einem Datentypen sagst Du etwas aus (sonst könnte man alles void* definieren):

    int i; // Bedeutung: In i sollen nur Zahlen aus N (in bestimmten Grenzen) abgelegt werden
    std::string s; // Bedeutung: Hier sollen Zeichenketten rein
    int& ref_i = i; // Bedeutung: Dies Ding soll ein Alias für i sein. Alles, was für i gilt, gilt auch für ref_i und andersherum
    std::string* ptr_s; // Bedeutung: Dieses KANN zwischendurch auf einen string zeigen
    ....
    

    Je nach zu programmierender Fachlichkeit ergibt Jedes seinen Sinn.
    Ein "Alias" ist z.B. sinnvoll, wenn eine Hutgröße verändert werden soll:

    void erhoeheZahl(int& zahl) { 
        // Hier ist total egal, was die Zahl dem Aufrufer bedeutet;
        // für uns ist es einfach "eine Zahl"
        zahl += 1;
    }
    
    int main(void) {
        int hutgroesse; //Hier soll augenscheinlich eine Hutgroesse abgelegt werden
        hutgroesse = 3;
        erhoeheZahl(hutgroesse); // ICH will, dass diese Hutgroesse als Zahl betrachtet und erhoeht wird
            // implizit mache ich hier "zahl = hutgroesse;" Da zahl eine Referenz ist (und nicht etwa selbst ein int), 
            // sorge ich dafuer, dass alles, was in erhoeheZahl() ebenfalls mit hutgroesse passiert
        ...
    

    Gruß,

    Simon2.


Anmelden zum Antworten