Hallo,
ich lese gerade "In C++ denke", auf Torstens Hinweis. Im Kapitel 10 wird von Referenzen gesprochen. Das ist mir noch etwas unklar. Sind das Referenzen wie in Java, nur mit dem Syntax von Zeigern in C?
Jan
Oftmals kann man Zeiger und Referenzen gleichermassen benutzen:
//referenz: void change(int& x){ x++; } ... int a=5; change(a); cout<<a; //gibt 6 aus
================================= //zeiger void change(int* x){ *x=(*x)+1; }
int a=5; change(&a); cout<<a;//gibt 6 aus
Zeiger und Referenzen sind sich also ziemlich aehnlich....
On 5/14/07, Jan Rakelmann JanRakelmann@web.de wrote:
Hallo,
ich lese gerade "In C++ denke", auf Torstens Hinweis. Im Kapitel 10 wird von Referenzen gesprochen. Das ist mir noch etwas unklar. Sind das Referenzen wie in Java, nur mit dem Syntax von Zeigern in C?
Jan
Lug-dd maillist - Lug-dd@mailman.schlittermann.de http://mailman.schlittermann.de/mailman/listinfo/lug-dd
Noch ein Hinweis aus der Praxis: Bei Funktionsdeklarationen besser Zeiger statt Referenzen benutzen, denn damit wird beim Aufruf der Funktion/Methode sofort deutlich dass mit der uebergebenen Variable was gemacht wird(bzw gemacht werden kann). (und nicht nur ein Input-Parameter ist)
On 5/14/07, Jan Rakelmann JanRakelmann@web.de wrote:
Hallo,
ich lese gerade "In C++ denke", auf Torstens Hinweis. Im Kapitel 10 wird von Referenzen gesprochen. Das ist mir noch etwas unklar. Sind das Referenzen wie in Java, nur mit dem Syntax von Zeigern in C?
Jan
Lug-dd maillist - Lug-dd@mailman.schlittermann.de http://mailman.schlittermann.de/mailman/listinfo/lug-dd
On Monday 14 May 2007, Frank Gerlach wrote:
Noch ein Hinweis aus der Praxis: Bei Funktionsdeklarationen besser Zeiger statt Referenzen benutzen, denn damit wird beim Aufruf der Funktion/Methode sofort deutlich dass mit der uebergebenen Variable was gemacht wird(bzw gemacht werden kann). (und nicht nur ein Input-Parameter ist)
Das gilt nur in Teams, die ANSI-C gewöhnt sind oder wenn es keine ordentliche Doku gibt.
Logikfrage: würdest Du bei dieser Funktionsdeklaration vermuten, dass x und y nicht geändert werden? class MyWindow { //... void getCoordinates(int&x,int&y); };
Sicherheitsfrage: wenn Du schon Pointer verwendest - kann man davon ausgehen, dass Du auch ganz gewissenhaft als erstes prüfst, ob der Zeiger gültig ist? Wirklich immer?
Konrad
On 5/14/07, Konrad Rosenbaum konrad@silmor.de wrote:
On Monday 14 May 2007, Frank Gerlach wrote:
Noch ein Hinweis aus der Praxis: Bei Funktionsdeklarationen besser
Zeiger
statt Referenzen benutzen, denn damit wird beim Aufruf der Funktion/Methode sofort deutlich dass mit der uebergebenen Variable was gemacht wird(bzw gemacht werden kann). (und nicht nur ein
Input-Parameter
ist)
Das gilt nur in Teams, die ANSI-C gewöhnt sind oder wenn es keine ordentliche Doku gibt.
Logikfrage: würdest Du bei dieser Funktionsdeklaration vermuten, dass x und y nicht geändert werden? class MyWindow { //... void getCoordinates(int&x,int&y); };
Bei vielen Funktionen/Methoden ist es nicht so eindeutig..... Und: was ist an einem Aufruf wie
int x,y; m_window->getCoordinates(&x,&y);
schwierig ? Wer natuerlich einen NULL pointer uebergibt wird ein SIGSEV ausloesen, was auch gut ist.
On Monday 14 May 2007, Frank Gerlach wrote:
Und: was ist an einem Aufruf wie
int x,y; m_window->getCoordinates(&x,&y);
schwierig ?
Nichts. Die Implementation von getCoordinates ist schwerer.
Wer natuerlich einen NULL pointer uebergibt wird ein SIGSEV ausloesen, was auch gut ist.
Das finde ich nicht dass das gut ist.
Stell Dir jetzt mal bitte ein richtig komplexes Programm vor, das auf X Plattformen laufen muss und morgen kriegst Du von einem Windowsluser angerufen: "das Programm geht nicht." - "Was geht nicht?" - "Stürzt ab." - "Was hast Du gemacht?" - "Nix!" ... etc.pp.
Und das alles nur, weil irgendwer nicht begriffen hatte, dass x und y keine optionalen Parameter sind und der selbe irgendwer keine Möglichkeit gefunden hat diesen Code gründlich zu testen.
Wenigstens irgendwo in einem Log muss bei sowas noch ein Kommentar stehen. "Segmentation fault." ermöglicht keine Diagnose.
Kurz: vertraue keinem Pointer - er wird Dich beissen.
Die korrekte Variante ist:
a) graceful ignorance: void MyWindow::getCoordinates(int*x,int*y) { if(x)*x=meinX(); if(y)*y=meinY(); }
oder wenn es eine kritische Funktion ist b) graceful failure: void MyWindow::repaintFromX(X11Connection*x11) { if(x11==0){ fprintf(stderr,"Fatal Error: it seems I lost the connection to X11. Halting application.\n"); exit(1); }else{ //... } }
Fast immer ist a) die richtige Variante. Das Programm einfach gegen die Speicherwand laufen zu lassen ist nie die richtige Variante.
Konrad
Frank Gerlach schrieb:
schwierig ? Wer natuerlich einen NULL pointer uebergibt wird ein SIGSEV ausloesen, was auch gut ist.
Und wenn Du -- was auch nicht selten ist -- einen nicht initialisierten Zeiger oder einen auf einen gelöschten Speicherbereich übergibst, dann bekommst Du u.U. alles mögliche, nur selten einen Speicherzugriffsfehler.
Sowas ist meist nur aufwändig zu klären.
Tobias
On Monday 14 May 2007, Jan Rakelmann wrote:
ich lese gerade "In C++ denke", auf Torstens Hinweis. Im Kapitel 10 wird von Referenzen gesprochen. Das ist mir noch etwas unklar. Sind das Referenzen wie in Java, nur mit dem Syntax von Zeigern in C?
Ohh Schreck, wenn man jetzt mein Java nicht so rostig wäre...
Es ist definitiv nicht java.lang.ref.*Reference* - das ist Teil der Java Reflection und existiert bei C++ in dieser Form nicht.
Eine C++ Referenz ist ein Alias für eine Variable.
Dazu muss man vom normalen C ausgehen, bei dem alles "by value" ist - wenn ich eine Variable zuweise oder an eine Funktion übergebe, dann wird der Wert (Inhalt) übergeben und nicht die Variable selbst. Wenn man auf die Variable selbst "von aussen" zugreifen will braucht man einen Pointer, den man auflöst und dann auf den Speicher direkt schreibt/liest.
Da Pointer etwas unhandlich und nicht sehr objektorientiert sind brauchte man einen Mittelweg: die Referenz. Referenzen lassen sich als Aliase für Variablen einsetzen oder erlauben es die Variable "selbst" an eine Funktion zu übergeben, so dass diese in die Variable schreiben kann ohne Pointer auflösen zu müssen.
Beispiel Alias:
int a; //das ist a a=42; //a ist jetzt 42 int &b=a; //b ist ein Alias für a int &c=b; //c ist ein Alias für a und b //klingt komisch, ist aber so... printf("%i\n",c); //das gibt jetzt 42 aus b+=8; //und weil a böse war schmuggeln wir ihm via b 8 drauf printf("%i == %i == %i\n",a,b,c); //und damit beweisen wir a == b == c == 50 int x=666; // das ist x, x ist ganz doll fies b=x; //a,b,c sind jetzt wesentlich größer printf("%i\n",a); //das gibt jetzt 666
Wie man leicht sieht(*) sind a, b, und c im Grunde die selbe Variable mit drei unterschiedlichen Namen. Gemeinerweise gibt es aber noch einen Unterschied zwischen "=" und "=". Gesehen? Nein? Das "=" bei der Deklaration der Referenz (int &b=a) sagt der Referenz für welche Variable sie ein Alias ist. Dieses "=" darf man auch nicht weglassen, sonst beschwert sich der Compiler. Im Unterschied dazu das "=" bei Zuweisungen (b=x) überträgt den Wert auf die Variable, die mit der Referenz bezeichnet wird - es ändert nicht die Assoziation der Referenz (das geht nicht).
(*)Ohh, ich liebe es diesen Spruch auf Mathematiker anzuwenden - statt wie in der Uni, wo Mathematiker den auf mich geschmissen haben. Ich sah nie irgendwas. ;-)
Beispiel Übergabe:
void addiere8(int & ref) //das ist eine Funktion mit Referenzargument { ref += 8 ; //wir addieren einfach mal was dazu }
main() { int x=2;//das ist x, x ist 2 addiere8(x); //jetzt ist x 10 printf("%i\n",x); //10 }
In dem Moment, wo ich addiere8(x) aufrufe wird innerhalb von addiere8 die Argumentvariable "ref" zum Alias für die externe Variable "x" und ich kann darauf schreibend zugreifen.
Du wirst übrigens recht häufig solche Konstrukte finden: void meineFunktion(const MeineKlasse&x);
Semantischt ist das identisch zu: void meineFunktion(MeineKlasse x);
also eine Úbergabe als Wert, den man nicht verändern und so verändert zurückgeben kann. Im Detail hat das aber zwei Unterschiede:
a) Du kannst den Wert auch nicht lokal/temporär nicht ändern (const). (Braucht man meistens aber auch nicht.)
b) Wenn MeineKlasse sehr gross ist, dann bringt die Referenz Geschwindigkeits- und Speichervorteile, da keine Kopie angelegt werden muss, sondern nur ein Alias definiert wird.
Konrad
On Monday 14 May 2007 16:34:41 Konrad Rosenbaum wrote:
(*)Ohh, ich liebe es diesen Spruch auf Mathematiker anzuwenden - statt wie in der Uni, wo Mathematiker den auf mich geschmissen haben. Ich sah nie irgendwas. ;-)
Sie haben dich bestimmt mit dem Beweis durch rekursiven Querverweis ausgetrickst. In Quelle A wird Satz 5 gefolgert aus Satz 3 in Quelle B, welcher seinerseits sofort aus Korollar 6.2 der Quelle C folgt, den man trivial aus Satz 5 der Quelle A erhält.
SC-fortunes-NR, Josef
lug-dd@mailman.schlittermann.de