>double dval = 3.14; // dval типа double; ее значение неизменно
>cptr = &dval; // ok: но изменить dval при помощи cptr нельзя
Подобно ссылке на константу, указатель на константу ничего не говорит о том, является ли объект, на который он указывает, константой. Определение указателя как указателя на константу влияет только на то, что с его помощью можно сделать. Не забывайте, что нет никакой гарантии того, что объект, на который указывает указатель на константу, не будет изменяться.
В отличие от ссылок, указатели — это объекты. Следовательно, подобно любым другим объектам, вполне может быть указатель, сам являющийся константой. Как и любой другой константный объект, константный указатель следует инициализировать, после чего изменить его значение (т.е. адрес, который он содержит) больше нельзя. Константный указатель объявляют, расположив ключевое слово >const
после символа >*
. Это означает, что данный указатель является константой, а не обычным указателем на константу.
>int errNumb = 0;
>int *const curErr = &errNumb; // curErr всегда будет указывать на errNumb
>const double pi = 3.14159;
>const double *const pip = π // pip константный указатель на
> // константный объект
Как уже упоминалось в разделе 2.3.3, проще всего понять эти объявления, читая их справа налево. В данном случае ближе всего к имени >curErr
расположен спецификатор >const
, означая, что сам объект >curErr
будет константным. Тип этого объекта формирует остальная часть оператора объявления. Следующий символ оператора объявления, >*
, означает, что >curErr
— это константный указатель. И наконец, объявление завершает базовый тип, означая, что >curErr
— это константный указатель на объект типа >int
. Аналогично >pip
— это константный указатель на объект типа >const double
.
Тот факт, что указатель сам является константой, ничто не говорит о том, можем ли мы использовать указатель для изменения основного объекта. Возможность изменения объекта полностью зависит от типа, на который указывает указатель. Например, >pip
— это константный указатель на константу. Ни значение объекта, на который указывает указатель >pip
, ни хранящийся в нем адрес не могут быть изменены. С другой стороны, указатель >curErr
имеет простой, неконстантный тип >int
. Указатель >curErr
можно использовать для изменения значения переменной >errNumb
:
>*pip = 2.72; // ошибка: pip - указатель на константу
>// если значение объекта, на который указывает указатель curErr
>// (т.е. errNumb), отлично от нуля
>if (*curErr) {
> errorHandler();
> *curErr = 0; // обнулить значение объекта, на который
> // указывает указатель curErr
>}
Упражнение 2.27. Какие из следующих инициализаций допустимы? Объясните почему.
>(a) int i = -1, &r = 0; (b) int *const p2 = &i2;
>(c) const int i = -1, &r = 0; (d) const int *const p3 = &i2;
>(e) const int *p1 = &i2; (f) const int &const r2;