Zeiger
-
NewBe schrieb:
warum z.B. *p=&a und dann unten p=&b ohne sternchen???
Das * gehört nicht zu der Zuweisung, sondern zur Typinformation - p ist ein "Zeiger auf int" aka "int*" und wird mit der Adresse (&) von a initialisiert.
Dann wird 32.1 ausgegeben. Da weise ich doch b aus pointer den Wert von a zu. Warum geht das nicht, wenn ich b die "Anfangsadresse von a" mit & zuweise.
Arrays werden bereits implizit in Pointer (auf ihr erstes Element) umgewandelt, wenn das nötig ist. Wenn du das explizit deutlich machen willst, kannst du
double* b=&a[0];schreiben.
-
Stelfer schrieb:
...
die unterschieden sich ziemlich stark voneinander...Hmmm finde ich jetzt nicht. Der einzige Unterschied ist doch, dass eine Referenz (während ihrer Lebenszeit) fest gebunden ist und ein Zeiger nicht.....
Wo siehst Du denn sonst noch (evtl. prinzipiellere) Unterschiede ?
Gruß,
Simon2.
-
Simon2 schrieb:
Der einzige Unterschied ist doch, dass eine Referenz (während ihrer Lebenszeit) fest gebunden ist und ein Zeiger nicht.....
Dann wäre nach Simon2 eine Referenz ein Zeiger (was natürlich Quatsch ist!) Referenz ist ein derefenzierter constanter Zeiger - könnte man schon eher sagen.

-
ollyx schrieb:
Simon2 schrieb:
Der einzige Unterschied ist doch, dass eine Referenz (während ihrer Lebenszeit) fest gebunden ist und ein Zeiger nicht.....
Dann wäre nach Simon2 eine Referenz ein Zeiger (was natürlich Quatsch ist!) ...
Was soll daran Quatsch sein ?
Worin besteht der Unterschied zwischenA a; A& aRef = a; A* const aPtr = &a;Doch höchstens:
- eine etwas anderen Syntax bei Zugriff und Zuweisung und
- evtl. noch dem Sonderfall der "Array-Pointer-Verquickung".
Das sind aber keine prinzipiellen Unterschiede (eher unglückliche "C-Altlasten", die sonst keinen Nährwert haben, sondern nur Schwierigkeiten bringen).
EDIT: OK, ein Unterschied ist mir noch eingefallen: Referenzen werden beim namelookup als äquivalenter (zum referenzierten Typen) betrachtet als Pointer... hmmm, finde ich das nun toll oder nicht ?
...Gruß,
Simon2.
-
Genau.
Bei Pointern und Referenzen handelt es sich um Variablen, deren Wert eine Adresse ist.
-
Die_Gute_Fee schrieb:
Genau.
Bei Pointern und Referenzen handelt es sich um Variablen, deren Wert eine Adresse ist... wobei Letztere selbst nicht mehr adressierbar ist.
Gruß,
Simon2.
-
Referenzen sind keine Objekte, mithin erst recht keine Variablen.
-
Referenzen sind nur Aliase, die nur im C++-Sourcecode existieren. Das ist der Sinn einer Referenz. Halt nur "ein anderer Name für eine Variable im Sourcecode". Klar, wenn ein Compiler so "doof" ist und daraus z.B. einen Pointer compiliert, ist das ein Implementierungs-Detail des Compilers. Aber vom C++-Standardpunkt aus gesehen, ist das nicht Sinn von Refs. Sonst hätten es auch gleich Pointer bleiben können. Gehe hier absolut mit camper konform.
-
Hi,
ich finde, dass sind ja alles schöne philosopische Aussagen über "das Wesen der Referenz als solcher" .... aber in der Praxis verwende ich doch Referenzen an denselben Stellen, wo ich sonst (*const)-Verwenden würde, oder ?
Und wurden sie nicht genau dafür eingeführt ?Mal andersherum:
...Sonst hätten es auch gleich Pointer bleiben können.
Ja ... warum eigentlich nicht ? Wo hat man eigentlich gewonnen dadurch, dass es Referenzen gibt ? Dadurch, dass man jetzt "Tipparbeit spart" ? ("." statt "->" bzw. kein "*" mehr; und bei der Übergabe spart man ein "&")...
Ich persönlich (da kann ich natürlich falsch liegen) sehe in Referenzen "moderne Pointer": Man kann nach der Typdefinition (und Bindung) komplett vergessen, dass man hier auf ein anderes Objekt referenziert (was z.B. bei templates nett ist, weil da derselbe Code für "A&"'s wie für "A"'s funktioniert)...
Trotzdem ist für mich die "Aussage" hinter (bzw. die Bedeutung) einer Referenz dieselbe wie hinter einem Pointer: "Eigentlich meine ich nicht Dich, sondern das, worauf Du verweist".Gruß,
Simon2.
-
Referenzen wurden eigeführt, weil Pointer einem bei iostreams nicht weiter helfen, sondern einem hinderlich sind.
io << var;Du machst ja nicht das
io << &var;Sondern du willst io DAS var-Objekt übergeben. Referenzen sind Namens-Aliase, kannst du im Stroustrup nachlesen (haben sich Camper und ich nicht aus der Nase gezogen!). Wenn du hier im Forum nicht nur Simon2 heißt, sondern auch Andreas2, ist Andreas2 eine Referenz von Simon2.
int a = 1; int &b = a; // b IST a. nicht mehr und nicht weniger. a heißt hier nur b. Nur ein anderer Name. int *p = &a; // p ist nicht a!!! Sondern ist ein Zeiger der auf a Zeigt.Es ist ein essenzieller Unterschied zu einem Pointer, weil ein Pointer eine eigenständige Variable ist.
Noch klarer wird es hier:
void foo(Hallo &a) { // a IST zur Laufzeit b!!! Nur ein anderes Namensschild. Physikalisch ist es b! } Hallo b; foo(b);Dessen muß man sich bewusst werden, das Referenzen nichts mit Pointern zu tun haben.
Artchi
PS: Eigentlich muß ich dir Pointer garnicht erklären, weißt du selber.

-
Hi,
danke für Deine Antwort.
So richtig überzeugt hast Du mich allerdings nicht ... auch nicht durch die Verlängerung des "Referenz-ist-Alias-und-nicht-Zeiger"-Mantras.
Dass "Zeiger" für den Nutzer als eigene Objekte sichtbar sind, ist für mich eh' nur eine C-Altlast-Eigenschaft, die bei den Referenzen inzwischen durch den Compiler (falls intern überhaupt noch so implementiert) versteckt wird.
Auch hinter dem Zeiger steht nur die Idee, ein Ding unter einem anderen Namen anfassen zu können (um so den Zugriff zu verallgemeinern) (dass dann irgendjemand die "geniale" Idee hatte, mittels "++" doch einfach mal im Speicher weiterpringen zu können, hat sich IMO nicht bewährt und eigentlich auch nichts mit dem Konzept eines Zeigers zu tun ...
- weswegen man da ja dann iteratoren eingefürt hat).Artchi schrieb:
...
io << var;Du machst ja nicht das
io << &var;Wieso sollte Zweiteres konzeptionell etwas Anderes sein als Ersteres ?
Da man zu Entwurfszeiten der IOStreams bereits Referenzen kannte, hat man sie in der Schnittstellendefinition verwendet und nicht Pointer - aber da sehe ich keine "magic".Nochmal deswegen die Frage: Wo und warum verwendest Du an bestimmten Stellen Referenzen und keine (*const) ? (*)
Gruß,
Simon2.
(*) vorgegebene Schnittstellen zählen nicht.
-
Würde das hier gehen, wenn du keine Refs hättest?
cout << "hallo" << 123 << b << endl;Deshalb ist es ein konzeptioneller Unterschied, ob du das hier machen müsstest:
io << &var;Weil du entweder einen Pointer vom <<-Operator zurück bekommen würdest, oder eine Objektkopie.
Nochmal deswegen die Frage: Wo und warum verwendest Du an bestimmten Stellen Referenzen und keine (*const) ? (*)
Habe ich noch nie benutzt. Sehe ich zum ersten mal.
Das hierA* const aPtr = &a;verstehe ich wiederrum nicht. Was hat das jetzt mit Refs zu tun? aPtr ist doch ein Pointer? Der ist doch was ganz anderes. Halt ein Zeiger. Wo setzt man ihn denn ein?
Referenzen benutze ich dann, wenn ich mit dem Objekt weiter arbeiten will, das ich vom Benutzer verlange. Ich verlange selten Pointer. Weil ich eigentlich nicht mit der Adresse arbeiten will, die interessiert mich meistens nicht die Bohne. Wenn ich eine Funktion schreibe, in der ich einen String verlange, interessiert mich doch die Adresse des Strings nicht. Ich will DEN String haben. Also benutze ich Refs.
Artchi
PS: Tipparbeit-Ersparnis interessiert mich bei Refs nicht (von wegen . statt ->), weil wenn ich in VisualAssist bei Pointern . drücke, VisualAssist autom. ein -> draus macht.

-
Artchi schrieb:
Würde das hier gehen, wenn du keine Refs hättest?
cout << "hallo" << 123 << b << endl;Deshalb ist es ein konzeptioneller Unterschied, ob du das hier machen müsstest:
?? warum das ?
Es gäbe eben die entsprechendenostream* operator<<(ostream*, char const *) ostream* operator<<(ostream*, int) und ostream* operator<<(ostream*, B const *);und der Call wäre halt
cout << "hallo" << 123 << &b << endl;Artchi schrieb:
io << &var;Weil du entweder einen Pointer vom <<-Operator zurück bekommen würdest, oder eine Objektkopie.
Ja, einen Pointer - und ?
Wenn wir keine Referenzen hätten, übernähmen die IOFunktionen alle Pointer statt Referenzen... außer dem "syntatkischen Zucker" (s. "spart Tipparbeit"), dass es ohne "*"- und "->" netter aussieht, sehe ich da kein Gegenargument.Artchi schrieb:
...aPtr ist doch ein Pointer? Der ist doch was ganz anderes. Halt ein Zeiger....
Simon2 schrieb:
... auch nicht durch die Verlängerung des "Referenz-ist-Alias-und-nicht-Zeiger"-Mantras. ;)...
Artchi schrieb:
Wo setzt man ihn denn ein?
...Na da, wo man den Zeiger nicht mehr "umbiegen" will:
void f(int& i) { i=2; } // (1) void f(int * const i) { *i = 2; } // (2) void g(int *i) { ++i; f(i); } // (3) void h(int * const i) { g(i); } // KRACH !! int main() { int iArr[10]; f(i[2]); // -> (1) f(&(i[2])); // -> (2) return 0; }Oder
int main() { char const * IrgendwasKonstantes = "Inhalt nicht ändern"; char const * const GenauDASLiteral = "Inhalt UND Verweis nicht ändern"; cout << IrgendwasKonstantes << " : " << GenauDASLiteral << "\n"; char const * MeinNeuerText = "Hey, das ist Neu"; IrgendwasKonstantes = MeinNeuerText; GenauDASLiteral = MeinNeuerText; // KRACH !!! return 0; }(*const) also genau da, wo ich einen "Verweis festnageln" will ... eben, wenn er IMMER auf dasselbe Objekt verweisen soll - Hoppla: Genau, wie eine Referenz.

Artchi schrieb:
...Ich verlange selten Pointer. Weil ich eigentlich nicht mit der Adresse arbeiten will, die interessiert mich meistens nicht die Bohne....
Ich behaupte mal, dass das Interesse an einer Speicheradresse insgesamt sehr gering und eher selten dei Motivation zur Benutzung eines Pointers ist.
Wenn, dann geht es eher darum, dass man "Verweise umhängen" können muss.
Folgendes wäre nämlich ohne Pointer nicht möglich:// Einfaches Beispiel: class A { B const * b; public: A(B const * initB) : b(initB) {} haenge_A_an_neues_B(B const * neuesB) { b = neuesB; } }; // oder etwas weniger offensichtlihes Beispiel std::vector<A*> v; // das klappt mit Referenzen nichtGruß,
Simon2.
-
Hallo,
mich würde mal interessieren, wofür Funktionszeiger eigentlich gut sein sollen.
Danke
-
basti33 schrieb:
mich würde mal interessieren, wofür Funktionszeiger eigentlich gut sein sollen.
Sie sind immer dann gut, wenn ein Aufruf weiterdelegiert werden muss, weil die aktuelle Funktion keine Ahnung hat, wie sie mit etwas umgehen soll. Funktionszeuger sind Member-Funktionen recht ähnlich (gehen aber eher in die andere Richtung, daher auch der Begriff "callback").
Konkretes Beispiel: Ich habe eine Sortier-Funktion, die generisch sein soll, d.h. beliebige Objekte sollen sortiert werden. Das Sortieren ist stets vergleichsbasiert, d.h. die Funktion muss wissen, welches von zwei Objekten a und b das kleinere ist. Da die Funktion generisch ist, weiß die Funktion das aber. Daher übergebe ich der Funktion nicht nur das zu sortierende Array sondern außerdem auch eine Funktion, die das eben weiß:
template <typename T> void sort(std::vector<T> const& array, int (*compare)(T, T)) { // ... }Diese Vergleichsfunktion funktioniert so, dass eine negative Zahl zurückgegeben wird, wenn das erste Objekt kleiner ist, 0, wenn beide gleich sind und sonst eine positive Zahl. Sie könnte für zwei Integer z.B. einfach folgendermaßen aussehen:
int compare_int (int a, int b) { return a - b; }Jetzt kann man die 'sort'-Funktion so aufrufen:
std::vector<int> vec; // Vektor füllen ... sort(vec, &compare_int);
-
Danke für deine Antwort. So ganz verstanden habe ich es aber nicht.
Konrad Rudolph schrieb:
Da die Funktion generisch ist, weiß die Funktion das aber.
Meinst du: Da die Funktion generisch ist, weiß die Funktion das aber nicht?
Außerdem versteh ich irgendwie nicht, wieso man so was nicht mit überladenen Funktionen löst.Danke