2016-11-27 4 views
1

Dies ist der Code const:Pointer auf Referenznullwert

const int x = 0; 
const int& r = x; 

const int* p1 = x; // Works (p1 = 0) 
const int* p2 = r; // error C2440: 'initializing': cannot convert from 'const int' to 'const int *' 

Warum ist p1 auf den Wert von x, aber p2 nicht?

Liegt es daran, dass p2 nicht garantieren kann, dass x konstant ist, wenn man nur auf r schaut?
Oder gibt es noch etwas subtiles über Referenzen, die diesen Fehler verursacht?

+1

'cosn int * p1 = x;' sollte nicht einmal kompilieren. Welchen Compiler benutzen Sie? – Rakete1111

+0

Ihr erster Versuch mit dem 'p1' ist auch nicht legal. Beide Zeigerinitialisierungen sind falsch. –

+0

VS 2015 mit/W4,/sdl und/WX on. Es kompiliert nicht, wenn x nicht konstant ist, sondern kompiliert mit const. – lousybyte

Antwort

3

Die dritte Zeile sollte einen Fehler verursachen. Es ist nicht in VS2015, denn wenn ein Fehler entweder im Compiler oder im Standard, je nachdem, welcher Standard angewendet wird. Andere Compiler geben Fehlermeldungen über diese Zeile aus.

Bevor C++ 11, jeder integraler Konstante Ausdruck, der auf 0 auswertet wird als Nullzeiger Konstante behandelt, so dass die erste Zeile entspricht const int* p1 = NULL;, It nicht p1 Punkt, um x.

Seit C++ 14 ist dies nicht mehr der Fall. Grob gesagt sind nur Literal Null und nullptr gültige Nullzeigerkonstanten.

Dazwischen, dh in C++ 11, erlaubt der Standard tatsächlich, dass konstante Ausdrücke, die auf Null ausgewertet werden, als Nullzeiger-Konstanten behandelt werden. Dies wird als Fehler im Standard angesehen. Es wurde in C++ 14 behoben. Einige Compiler (gcc, clang) entscheiden sich, den Fehler sofort zu beheben und einen Fehler selbst im C++ 11-Modus zu melden. VS2015 nicht.

Die vierte Zeile war in keiner Version von C++ gültig, da der Typ r eine Referenz und keine Ganzzahl ist.

+0

Ich habe keinen Hinweis auf diesen Fehler im Internet gefunden. Wissen Sie zufällig, ob es ein offenes Problem oder offizielle Informationen von MS gibt (vielleicht "wird nicht behoben")? –

+3

C++ 11 besagt, dass "eine Nullzeigerkonstante ein Integralkonstantenausdruck (5.19) Prvalue des Integer-Typs ist, der Zero oder einen Prvalue des Typen Std :: nullptr_t" auswertet. Offenbar wurde es als ein Defekt in der Norm und wurde in 14 geändert. Eine verwandte Antwort: http://StackOverflow.com/A/40787595/2456565 – krzaq

+0

@ Krzaq guten Fang –

-1

Pointers stellen die Adresse Wert, so dass Ihr Zeiger zu initialisieren, sollten Sie die "Adresse-of" Operator: &

const int *p1 = &x; 
const int *p2 = &r; 

Sie sind in der Lage einen Zeiger auf 0 einzustellen (die ist keine gültige Adresse auf einem PC), denn das ist die gleiche Einstellung wie NULL.

+0

Ich weiß, dass ich absichtlich die Zeigeradresse auf Null setzen. Dies ist nur für akademische Zwecke. – lousybyte

+0

* "Sie können einen Zeiger auf 0 setzen (was keine gültige Adresse auf einem PC ist), denn das ist die gleiche Sache wie auf' NULL' setzen "* C++ hat keine' NULL', wirklich; Es wird abgeraten. Der Standard erwähnt ausdrücklich, dass das Literal "0" verwendet werden kann, um irgendeinen Zeiger als einen durch die Implementierung definierten Nullzeigerwert zu initialisieren. Und C++ 11 (nur) erlaubt, dass irgendein "constexpr", der zu "0" auswertet, auch dafür verwendet wird. – StoryTeller

+0

* "Sie können einen Zeiger auf 0 setzen (was keine gültige Adresse auf einem PC ist), denn das ist die gleiche Einstellung wie auf NULL." * Nicht so, wie er es in seinem Code macht, nein . –