2016-11-27 3 views
1

Это код:Указатель ссылки на константные нулевое значение

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 *' 

Почему p1 набор к значению х, но p2 нет?

Это потому, что p2 не может гарантировать, что x является const, просто глядя на r?
Или есть что-нибудь еще тонкое в отношении ссылок, вызывающих эту ошибку?

+1

'cosnt int * p1 = x;' даже не компилировать. Какой компилятор вы используете? – Rakete1111

+0

Ваша первая попытка с 'p1' также не является законной. Обе инициализации указателя неверны. –

+0

VS 2015 с/W4,/sdl и/WX on. Он не компилируется, если x не const, но компилируется с константой. – lousybyte

ответ

3

Третья строка должна вызывать ошибку. Это не в VS2015, потому что если ошибка в компиляторе или в стандарте, в зависимости от того, какой стандарт применяется. Другие компиляторы выдают сообщения об ошибках в этой строке.

Перед C++ 11, любой интегральная константа, которая вычисляется в 0 рассматриваются как постоянный нулевого указателя, поэтому первая линия эквивалентна const int* p1 = NULL;, он не делает точку p1 к й.

С C++ 14 это уже не так. Грубо говоря, только буквальный ноль и nullptr являются действительными константами указателя на указатель.

Между тем, то есть в C++ 11, стандарт фактически допускает постоянные выражения, которые оцениваются в ноль, которые рассматриваются как константы нулевого указателя. Это считается дефектом стандарта. Он был исправлен в C++ 14. Некоторые компиляторы (gcc, clang) сразу же исправляют дефект и сообщают об ошибке даже в режиме C++ 11. VS2015 нет.

Четвертая строка никогда не была действительной ни в одной из версий C++, потому что тип r является ссылкой, а не целым числом.

+0

Я не нашел ссылки на эту ошибку в Интернете. Вы случайно не знаете, есть ли для этого открытая проблема или какая-либо официальная информация от MS (возможно, «не исправит»)? –

+3

C++ 11 утверждает, что «константа нулевого указателя представляет собой целочисленное константное выражение (5.19) prvalue целочисленного типа, которое вычисляет нуль или значение типа std :: nullptr_t.». По-видимому, это было признано дефектом в стандарте и было изменено в 14. Связанный ответ: http://stackoverflow.com/a/40787595/2456565 – krzaq

+0

@krzaq хороший улов –

-1

Указатели представляют адрес значение, так инициализировать указатели вы должны использовать «Адреса» оператор: &

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

Вы в состоянии установить указатель на 0 (который не является действительным адресом на ПК), потому что это то же самое, что и установка NULL.

+0

Я знаю, что я намеренно устанавливаю адрес указателя равным нулю. Это просто для академических целей. – lousybyte

+0

* «Вы можете установить указатель на 0 (что не является допустимым адресом на ПК), потому что это то же самое, что установка его на« NULL »* * C++ не имеет' NULL', действительно; его использование не рекомендуется. В стандарте явно упоминается, что литерал '0' может быть использован для инициализации любого указателя как значения, указанного в нулевом указателе. И C++ 11 (только) позволяет использовать любой 'constexpr', который оценивает' 0' для этого. – StoryTeller

+0

* «Вы можете установить указатель на 0 (что не является допустимым адресом на ПК), потому что это то же самое, что установка его в NULL.» * Не так, как он делает это в своем коде, нет , –

Смежные вопросы