Was ist das Ergebnis des Referenzoperators "&" bei const-Variablen?

7

Ich wurde gefragt, wie der Wert einer const-Variablen geändert werden kann.

Meine offensichtliche Antwort war "Zeiger!" aber ich habe das nächste Stück Code ausprobiert und ich bin verwirrt ...

%Vor%

Und die Ausgabe war:

%Vor%

Nun bin ich nicht sicher, was genau von '& amp; x' zurückgegeben wird, aber es ist definitiv nicht die tatsächliche Adresse von x, da der Wert bei x nicht geändert wurde!

Aber auf der anderen Seite enthalten ptr den Wert von x am Anfang! Also, was genau ist das?

BEARBEITEN mit VS2010 kompiliert

    
Avraham Shukron 13.11.2011, 22:05
quelle

5 Antworten

15

Ihr Programm ruft undefiniertes Verhalten auf (das Schreiben in eine const-Variable über einen Zeiger ist ein undefiniertes Verhalten), so dass alles passieren kann. Dies ist die wahrscheinlichste Erklärung, warum Sie das Verhalten Ihrer speziellen Implementierung erhalten:

Wenn Sie &x eingeben, erhalten Sie die Adresse von x . Wenn Sie *ptr = 6 eingeben, schreiben Sie 6 in x 's Speicherort. Wenn Sie jedoch cout << x ausführen, lesen Sie nicht wirklich aus dem Speicherort von x , da Ihr Compiler den Code optimiert hat, indem Sie hier x durch 5 ersetzt haben. Da x const ist, darf der Compiler dies tun, da es kein legales C ++ - Programm gibt, in dem dies das Verhalten des Programms ändern würde.

    
sepp2k 13.11.2011, 22:11
quelle
2

Der Compiler speichert x in einem Register, so dass sich der Wert im Speicher ändert, aber der letzte Ausdruck immer noch derselbe ist. Überprüfen Sie die generierte Assembly (kompilieren Sie mit -s ).

    
Nikolai Fetissov 13.11.2011 22:09
quelle
2

Zunächst ist dieses Verhalten nicht definiert. Das heißt, hier ist, was wahrscheinlich los ist:

Wenn Sie dies tun:

%Vor%

Der 5 wird an irgendeiner Adresse irgendwo gespeichert. Deshalb scheint der Zeiger richtig zu funktionieren. (obwohl das Konstanten wegwerfen ist immer noch undefiniertes Verhalten)

Aufgrund von Compileroptimierungen wird x = 5 jedoch nur als Literal in die finale Druckanweisung eingefügt. Der Compiler hält dies für sicher, weil x für const deklariert ist.

%Vor%

Deshalb drucken Sie den ursprünglichen Wert 5 aus.

    
Mysticial 13.11.2011 22:11
quelle
1

Vielleicht haben Sie einen Nebeneffekt der Codeoptimierung, versuchen Sie, den gleichen Code auszuführen, indem Sie alle Optimierungen deaktivieren, oder überprüfen Sie den asm-generierten Code. Ich nehme an, dass der Compiler den Wert, den er in einer Registry hat, wieder verwendet, da er auf const gesetzt hat. Selbst wenn Sie den Wert tatsächlich ändern, wird der geänderte Wert nicht korrekt weitergegeben. Die Gründe dafür, wie Keith in den Kommentaren bemerkte, sind, dass Sie mit einem undefinierten Verhalten paktieren.

    
Felice Pollano 13.11.2011 22:09
quelle
0

Was von &x zurückgegeben wird, ist ein Zeiger auf const int (d. h. int const* ). Nun werden Zeiger implementiert, die die Adresse enthalten, aber Zeiger sind keine Adressen, und Ihr Beispiel zeigt recht gut warum: Der Typ des Zeigers, obwohl zur Laufzeit nicht vorhanden, spielt immer noch eine wichtige Rolle .

In deinem Fall wirfst du das const weg und lügst damit dem Compiler "dieser Zeiger zeigt auf einen nichtkonstanten Int". Der Compiler weiß jedoch aus der Deklaration, dass sich der Wert von x nicht ändern kann (er wurde als const deklariert), und benutzt diese Tatsache frei (und der Standard erlaubt es: Ihr Versuch, ihn durch einen Zeiger in non-const int zu ändern ist undefiniertes Verhalten und daher darf der Compiler nichts tun.)

    
celtschk 13.11.2011 22:17
quelle

Tags und Links