Zeiger und Referenz - äquivalent?
-
Jap, nen constanter pointer ist das glecihe wie ne Referenz, also sind referenzen ins sofern unnötig, weil mit pointern alles abgedeckt wäre, aber durch das mittel der referenzen, kann man viele dinge "schöner" ausdrücken, was dazu führt, dass man heute ja auch kaum noch constandte pointer benutzt.
Anmerkung, es geht um Pointer, deren Adresse constant ist, nicht die Objekte auf die sie Zeigen, wird leider manchmal missverstanden!
-
xBlackKnightx schrieb:
ah ok, aber abgesehen von einmaliger Zuweisung isses schon äquivalent, also beide weisen auf die Variable 5 zu, oder?
klar, intern sind referenzen auch bloss pointer. für den c++ user stellt es sich nur anders dar, syntaktisch und semantisch (wie ich es hasse, diese vokabeln aus der linguistik auf's programmieren anzuwenden)
-
Slin schrieb:
Jap, nen constanter pointer ist das glecihe wie ne Referenz, also sind referenzen ins sofern unnötig, weil mit pointern alles abgedeckt wäre, aber durch das mittel der referenzen, kann man viele dinge "schöner" ausdrücken, was dazu führt, dass man heute ja auch kaum noch constandte pointer benutzt.
Das scheint eine reine Stilfrage zu sein. Stroustrup z.B. empfiehlt, konstante Zeiger statt Referenzen in Argumenten zu verwenden, damit der Benutzer beim Aufruf der Funktion explizit die Adresse übergeben muss und man dadurch sofort sieht, dass eine Referenz und nicht der Wert übergeben wird.
-
Beobachter schrieb:
Naja, finde schon. Nämlich insofern, das sich dieses Verhalten (einmalige Zuweisung, anschließend konstant),
wie man es von Referenzen gewohnt ist, sehr wohl auch mit Zeigern nachbilden lässt.Ist schon richtig, dass man damit teilweise das Verhalten von Referenzen mit Zeigern nachbilden kann. Deswegen sind sie noch lange nicht äquivalent. Und einen entscheidenden Unterschied, nämlich dass Referenzen immer auf ein gültiges Objekt verweisen, Zeiger aber nicht zwangsläufig, kann man damit auch nicht umgehen.
Konrad Rudolph schrieb:
Das scheint eine reine Stilfrage zu sein. Stroustrup z.B. empfiehlt, konstante Zeiger statt Referenzen in Argumenten zu verwenden, damit der Benutzer beim Aufruf der Funktion explizit die Adresse übergeben muss und man dadurch sofort sieht, dass eine Referenz und nicht der Wert übergeben wird.
Wie du schon sagst, es ist eine reine Stilfrage. Für Leute, für die lediglich die Entität als solche interessant ist, ist es völlig bedeutungslos, ob sie jetzt explizit die Adresse bei der Parameterübergabe erkennen (&foo) oder einfach nur den Bezeichner (foo).
-
groovemaster schrieb:
Und einen entscheidenden Unterschied, nämlich dass Referenzen immer auf ein gültiges Objekt verweisen, Zeiger aber nicht zwangsläufig, kann man damit auch nicht umgehen.
So wäre es schön, aber leider Zeigen auch Referenzen nicht immer auf gültige Objekte! Referenzen können sehr wohl auf undefinierte Speicherbereiche zeigen, genauso wie sie auch auf NULL zeigen können.
In meinen Augen sind und bleiben sie also äquivalent.int *a =NULL; int &b = *a; //Referenz auf a // b zeigt auf NULL
int * = new int (5); int &b = *a; //Referenz auf a delete a; // b zeigt jetzt ins Nirvana
Konrad Rudolph schrieb:
Das scheint eine reine Stilfrage zu sein.
Aber dem schließ ich mich gerne an!
-
Slin schrieb:
So wäre es schön, aber leider Zeigen auch Referenzen nicht immer auf gültige Objekte! Referenzen können sehr wohl auf undefinierte Speicherbereiche zeigen, genauso wie sie auch auf NULL zeigen können.
Der Unterschied liegt aber im undefinierten verhalten.
int *a =NULL; int &b = *a; //Referenz auf a // b zeigt auf NULL
Nein. Das ist leider kein korrektes C++
int * = new int (5); int &b = *a; //Referenz auf a delete a; // b zeigt jetzt ins Nirvana
lustig, aber beachte mal:
du kannst mit der referenz nichts mehr machen, mit einem Zeiger könntest du aber noch sachen aufführen und ihn lustig an funktionen übergebensprich: das mit referenzen ist quasi undefiniertes verhalten, mit zeigern keins.
Es mag dich schockieren, aber Zeiger können wirklich 0 sein. Was einen bedeutenden Unterschied ausmacht: nämlich gültig/ungültig. das ist mit referenzen nicht möglich.
ob man ein swap() jetzt mit zeigern oder referenzen macht, ist tatsächlich stil sache. aber ob zeiger und referenzen äquivalent sind, ist keine stilfrage sondern genau definiert: nämlich mit der antwort "nein"
-
Also ich seh immernoch keinen Unterschied..... obwohl deine Aussagen sehr überzeugend klingen.
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.
Alles frage des Stils, und das mein Code oben nicht sehr stilvoll ist, bzw nichtmal richtiges C++ ist mir auch klar, wollte nur demonstrieren, dass eine referenz sehr wohl auf NULL zeigen kann
-
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.htmlDas 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.