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;
(g) const int i2 = i, &r = i;
Упражнение 2.28. Объясните следующие определения. Какие из них недопустимы?
(a) int i, *const cp; (b) int *p1, *const p2;
(c) const int ic, &r = ic; (d) const int *const p3;
(e) const int *p;
Упражнение 2.29. С учетом переменных из предыдущих упражнений, какие из следующих присвоений допустимы? Объясните почему.
(a) i = ic; (b) pi = p3;
(с) pi = ⁣ (d) p3 = ⁣
(e) p2 = pi; (f) ic = *p3;
2.4.3. Спецификатор const
верхнего уровня
Как уже упоминалось, указатель — это объект, способный указывать на другой объект. В результате можно сразу сказать, является ли указатель сам константой и являются ли константой объекты, на которые он может указывать. Термин спецификатор const
верхнего уровня (top-level const
) используется для обозначения того ключевого слова const
, которое объявляет константой сам указатель. Когда указатель способен указывать на константный объект, это называется спецификатор const
нижнего уровня (low-level const
).
В более общем смысле спецификатор const
верхнего уровня означает, что объект сам константа. Спецификатор const
верхнего уровня может присутствовать в любом типе объекта, будь то один из встроенных арифметических типов, тип класса или ссылочный тип. Спецификатор const
нижнего уровня присутствует в базовом типе составных типов, таких как указатели или ссылки. Обратите внимание, что ссылочные типы, в отличие от большинства других типов, способны иметь спецификаторы const
как верхнего, так и нижнего уровня, независимо друг от друга.