001
27.03.2019, 10:57 Uhr
ao
(Operator)
|
Deine Erklärungen zu w sind nicht richtig, glaube ich. Gehen wir es durch.
int w = 1; int x = w; Das erzeugt zwei Variablen w und x. w bekommt den Wert 1 und x eine Kopie von w, also auch 1. Dabei behält w seinen Wert, und x und w sind ab jetzt unabhängig voneinander. Dass der Inhalt von w nach x bewegt wird und w danach keinen Wert mehr hat, das gibt es auch und nennt sich "Move-Semantik". Ist aber eine ganz andere Baustelle, hier wird kopiert.
int& y = x; y ist kein "Adressoperator", wie du sagst, sondern eine Referenz auf x. Man könnte auch sagen, ein Alias. Alles, was man mit y macht, macht man in Wahrheit mit x. Am Wert von x ändert sich an dieser Stelle nichts.
int* z = &w; Hier wird ein Zeiger erzeugt, der auf den Speicherort von w verweist. Der Wert von w ändert sich dadurch nicht.
Der Unterschied zwischen y und z ist, dass y, solange es lebt, immer eine Referenz auf x ist. Es ist nicht möglich, y zu einem späteren Zeitpunkt auf etwas anderes, z.B. auf w, verweisen zu lassen. Der Zeiger z hingegen kann sehr wohl auf andere Stellen im Speicher zeigen als auf w, wie wir noch sehen werden.
w += 1; Der Wert von w wird von 1 auf 2 erhöht.
x += 2; Der Wert von x wird von 1 auf 3 erhöht. Da y eine Referenz auf x ist, ändert sich gleichzeitig der Wert von y auf 3.
y += 3; Der Wert von y wird von 3 auf 6 erhöht. Da y selbst keine Variable ist, sondern eine Referenz auf x, ändert sich hier genaugenommen der Wert von x.
z += 4; Der Zeiger z wird um 4 erhöht. Beachte, dass der Zeiger selbst verändert wird, er zeigt also jetzt auf eine andere Speicherstelle, nicht mehr auf die Adresse von w. z wird nicht dereferenziert (das wäre *z), der Wert von w bleibt also unverändert. Tatsächlich zeigt z jetzt auf irgendwas (keine Ahnung, auf was), so dass ein Zugriff auf diese Adresse (*z = bla irgendein zufälliges Verhalten hervorbringen würde. Vom sofortigen Absturz über beliebige Seiteneffekte (z.B. Veränderungen anderer Variabler) bis zu scheinbarer völliger Wirkungslosigkeit ist alles möglich.
foo(x,y,z); x, y und z werden auf unterschiedliche Weise an foo übergeben: x (aktueller Wert 6) wird by-value an a übergeben, lokale Änderungen an a sind außerhalb von foo nicht sichtbar. y (aktueller Wert 6) wird by-reference an b übergeben. b wird so zu einem weiteren Alias auf x. Lokale Änderungen an b wirken sich auf y (und damit auf x) aus. Der Zeiger z wird by-value an c übergeben. Lokale Änderungen an c sind außerhalb von foo nicht sichtbar.
Innerhalb von foo: a += 1; a (das eine unabhängige Kopie des Wertes von x enthält) wird erhöht. Keine weiteren Auswirkungen.
b += 2; b (das eine Referenz auf y und damit eine Referenz auf x ist) wird um 2 erhöht. Außerhalb von foo erhöhen sich damit x und y von 6 auf 8.
c += 3; Wieder wird ein Zeiger weitergezählt und zeigt auf irgendwas Undefiniertes.
An dieser Stelle ist foo zuende und wird verlassen.
cout << w << y << endl; Die aktuellen Werte (2 und 8) werden ausgegeben. Dieser Post wurde am 27.03.2019 um 11:01 Uhr von ao editiert. |