Zeiger und Referenz - äquivalent?



  • Slin schrieb:

    Belassen wir es dabei, dass sich constante Pointer und Referenzen sehr sehr ähnlich sind, und sie in der Praxis (fast) äquivalent eingesetzt werden können.

    Ich sage nur: NULL-Zeiger
    (das ist ein signifikanter unterschied)

    Auch können Zeiger besitzend sein, referenzen nur, wenn man sehr pervers ist.



  • Der Unterschied kann sogar sehr groß sein. Wenn 1000 Zeiger auf den gleichen Platz verweisen, werden zur Laufzeit 1000 Speicherplätze für Zeiger und der Speicherplatz auf den verwiesen wird benutzt. Bei 1000 Referenzen auf den gleichen Platz wird zur Laufzeit nur der Speicherplatz auf den verwiesen wird benutzt, da Referenzen einfach nur Aliase (also verschiedene Variablennamen) für den selben Speicherplatz sind und somit nur zur Übersetzungszeit eine Rolle spielen.

    Siehe auch:
    http://www-ang.kfunigraz.ac.at/~haasegu/Lectures/Kurs-C/Script/html/node62.html



  • Verweiser schrieb:

    Der Unterschied kann sogar sehr groß sein. Wenn 1000 Zeiger auf den gleichen Platz verweisen, werden zur Laufzeit 1000 Speicherplätze für Zeiger und der Speicherplatz auf den verwiesen wird benutzt. Bei 1000 Referenzen auf den gleichen Platz wird zur Laufzeit nur der Speicherplatz auf den verwiesen wird benutzt, da Referenzen einfach nur Aliase (also verschiedene Variablennamen) für den selben Speicherplatz sind und somit nur zur Übersetzungszeit eine Rolle spielen.

    Siehe auch:
    http://www-ang.kfunigraz.ac.at/~haasegu/Lectures/Kurs-C/Script/html/node62.html

    Das stimmt so nur zum Teil:

    class CFoo
    {
    public:
        CFoo(int& rBar) :
            m_rBar(rBar)
        {}
    
    protected:
       int& m_rBar;
    };
    

    Hier ist die Referenz nicht nur ein alias, wenn man statt dessen einen const pointer wählen würde, würde die Klasse gleichgroß sein, auch ein const pointer muss im construktor intialisiert werden 😉

    Also ich tendiere auch zu "sehr ähnlich".

    MfG
    DDR-RAM



  • Verweiser schrieb:

    Der Unterschied kann sogar sehr groß sein. Wenn 1000 Zeiger auf den gleichen Platz verweisen, werden zur Laufzeit 1000 Speicherplätze für Zeiger und der Speicherplatz auf den verwiesen wird benutzt. Bei 1000 Referenzen auf den gleichen Platz wird zur Laufzeit nur der Speicherplatz auf den verwiesen wird benutzt, da Referenzen einfach nur Aliase (also verschiedene Variablennamen) für den selben Speicherplatz sind und somit nur zur Übersetzungszeit eine Rolle spielen.

    Das mag stimmen, wenn du so etwas machst:

    int a;
    int& b = a;
    

    Allerdings fällt das meistens auch hier unter den Punkt Optimierung und hängt vom Compiler ab. Außerdem verwendet niemand Referenzen in diesem Zusammenhang; normalerweise werden sie ja zur Parameterübergabe an Funktionen und als Rückgabewerte von Methoden (besonders Operatorüberladungen) benötigt, und da muß die Referenz auch im Speicher existieren!

    Zur Glaubensfrage 😉 : AFAIK implementieren die meisten Compiler Referenzen wie const-Zeiger (z.B. int* const ptr), die beim Zugriff automatisch dereferenziert werden.

    Moritz



  • referenzen als funktionsparameter versichern dem programmierer der funktion, dass das übergebene objekt wirklich existiert, zeiger tun dies nicht(man kann bei referenzen ja auch nicht drauf testen).

    wenn jemand meint eine referenz auf ein nicht existierendes objekt legen zu müssen ist das seine sache, ändert aber nix daran, dass die funktion trotzdem damit rechnet.

    const pointer hingegen versichern rein garnichts, zumindest wenn sie an eine funktion übergeben werden(und sonst auch nur, dass sich der ort auf den der zeiger zeigt sich nicht ändert).



  • otze schrieb:

    referenzen als funktionsparameter versichern dem programmierer der funktion, dass das übergebene objekt wirklich existiert, zeiger tun dies nicht(man kann bei referenzen ja auch nicht drauf testen).

    Richtig, ich bin aber der Frage nicht umsonst etwas ausgewichen und habe, um trotzdem auch meinen Senf beizutragen, von der Implementation geschrieben ;)!



  • Slin schrieb:

    So wäre es schön, aber leider Zeigen auch Referenzen nicht immer auf gültige Objekte!

    Mag schon sein, nur hast du dann halt auch kein gültiges Programm mehr. Was du in deinen Beispielen machst, ist erstens eine Nullreferenz erzeugen. Der Standard schreibt aber vor, dass das Benutzen von "Nullreferenzen" kein gültiges C++ ist. Und zweitens, mit

    delete a;
    

    machst du den Zeiger ungültig, womit wir wieder beim Thema wären, dass Zeiger nicht immer auf ein gültiges Objekt zeigen müssen.
    Zeig mir mal ein Beispiel (ohne Zeiger), wo du eine Referenz auf ein ungültiges Objekt verweisen lässt. Natürlich nur in gültigem C++, also solche Geschichten, wie zB eine Referenz auf eine lokale Variable aus einer Funktion zurückzugeben, sind auch tabu.

    Slin schrieb:

    Belassen wir es dabei, dass sich constante Pointer und Referenzen sehr sehr ähnlich sind

    Ähnlich heisst aber noch lange nicht äquivalent. Und warum bringst du immer wieder konstante Zeiger? Ich weiss nicht, ob der Threadersteller wirklich konstante Zeiger gemeint hat oder einfach nur generell Zeiger.



  • groovemaster schrieb:

    Slin schrieb:

    Belassen wir es dabei, dass sich constante Pointer und Referenzen sehr sehr ähnlich sind

    Ähnlich heisst aber noch lange nicht äquivalent. Und warum bringst du immer wieder konstante Zeiger? Ich weiss nicht, ob der Threadersteller wirklich konstante Zeiger gemeint hat oder einfach nur generell Zeiger.

    Konstante Zeiger, weil sie so wie Referenzen nur einmal zugewiesen werden können. Mit konstanten Zeigern kann man (fast) genau das Gleiche machen, wie mit Referenzen.

    ein Unterschied ist z.B.:

    int& foo	= *(new int);
    	((int*)&foo) = NULL;		//	ungültig
    	delete &foo;
    
    	int * const bar = new int;
    	((int*)bar) = NULL;			//	gültig
    	delete bar;
    

    Man kann das const bei const pointern wegcasten, bei Referenzen hingegen nicht!

    MfG
    DDR-RAM



  • DDR-RAM schrieb:

    Konstante Zeiger

    Da ich kein Hellseher bin, wirst du mir es hoffentlich nicht übel nehmen, wenn ich die Aussage erstmal vollkommen ignoriere. Und da der Threadersteller in seinem Beispielcode keine konstanten Zeiger benutzt, bestärkt mich das noch mehr, dass er nicht speziell von konstanten Zeigern gesprochen hat.

    DDR-RAM schrieb:

    int& foo	= *(new int);
    	((int*)&foo) = NULL;		//	ungültig
    	delete &foo;
    

    Dir wird es vielleicht entgangen sein, aber der Code ist nicht deshalb ungültig, weil eine Referenz im Spiel ist, sondern weil du schlichtweg keinen l-value hast. Und warum verwendest du einen Cast? &foo ist doch bereits vom Typ int*.



  • groovemaster schrieb:

    Zeig mir mal ein Beispiel (ohne Zeiger), wo du eine Referenz auf ein ungültiges Objekt verweisen lässt. Natürlich nur in gültigem C++, also solche Geschichten, wie zB eine Referenz auf eine lokale Variable aus einer Funktion zurückzugeben, sind auch tabu.

    Wird es nicht geben, da hast du absolut recht, da muss man gegen den Standard verstoßen, in sofern bin ich jetzt entgültig überzeugt, dass sie nicht äquivalent sind. Aber wer in diesem Forum nutzt schon den Standard *ugly* 😃

    groovemaster schrieb:

    Und warum bringst du immer wieder konstante Zeiger? Ich weiss nicht, ob der Threadersteller wirklich konstante Zeiger gemeint hat oder einfach nur generell Zeiger.

    Er meinte wohl generell Zeiger, aber wenn ich mich nciht täusche, war darauf auch schnell eine Antwort gefunden!



  • groovemaster schrieb:

    Da ich kein Hellseher bin, wirst du mir es hoffentlich nicht übel nehmen, wenn ich die Aussage erstmal vollkommen ignoriere. Und da der Threadersteller in seinem Beispielcode keine konstanten Zeiger benutzt, bestärkt mich das noch mehr, dass er nicht speziell von konstanten Zeigern gesprochen hat.

    Ich rede von const Zeigern, da const Zeigern den Referenzen näher sind als normale Zeiger. Aus der Frage des Threaderstellers entwickelte sich eine Diskusion, also muss man sich nicht nur auf den Threadersteller beziehen.

    DDR-RAM schrieb:

    int& foo	= *(new int);
    	((int*)&foo) = NULL;		//	ungültig
    	delete &foo;
    

    Dir wird es vielleicht entgangen sein, aber der Code ist nicht deshalb ungültig, weil eine Referenz im Spiel ist, sondern weil du schlichtweg keinen l-value hast. Und warum verwendest du einen Cast? &foo ist doch bereits vom Typ int*.

    Ich weiß schon was ich da gemacht habe und warum das ungültig ist.
    Es ging nur um einen Vergleich, const pointer mit Referenz, der einen Unterschied darlegen sollte. (address of referenz != value of const pointer,
    das eine ist ein R-Wert, wie du schon sagtest, das andere ein L-Wert, der konstant ist)
    Aber, da du sowieso streng dagegen bist Ähnlichkeiten zu sehen, brauch ich meine Erläutungen nicht weiter fortführen. 😉

    Fazit:
    Referenzen sind keine Pointer.
    Referenzen haben gewisse Ähnlichkeiten mit Pointern.
    Referenzen sind const Pointern noch ähnlicher, aber noch lange nicht äquivalent.

    Nichts neues also. 🙂

    MfG
    DDR-RAM



  • DDR-RAM schrieb:

    address of referenz

    Was soll das sein? Meinst du das hier?
    [cpp]((int*)&foo) = NULL;[/cpp]
    Wie hier bereits erwähnt wurde, ist eine Referenz ein Alias. Du holst dir hier also nicht die Adresse der Referenz, sondern des referenzierten Objektes. Praktisch gesehen hast du folgendes

    ((int*)&*(new int)) = NULL;
    

    DDR-RAM schrieb:

    Aber, da du sowieso streng dagegen bist Ähnlichkeiten zu sehen

    Ich habe nie gesagt, dass es keine Ähnlichkeiten gibt, nur sind sie halt auch nicht äquivalent.


Anmelden zum Antworten