Как уже упоминалось в разделе 2.3.3, проще всего понять эти объявления, читая их справа налево. В данном случае ближе всего к имени curErr
расположен спецификатор const
, означая, что сам объект curErr
будет константным. Тип этого объекта формирует остальная часть оператора объявления. Следующий символ оператора объявления, *
, означает, что curErr
— это константный указатель. И наконец, объявление завершает базовый тип, означая, что curErr
— это константный указатель на объект типа int
. Аналогично pip
— это константный указатель на объект типа const double
.
Тот факт, что указатель сам является константой, ничто не говорит о том, можем ли мы использовать указатель для изменения основного объекта. Возможность изменения объекта полностью зависит от типа, на который указывает указатель. Например, pip
— это константный указатель на константу. Ни значение объекта, на который указывает указатель pip
, ни хранящийся в нем адрес не могут быть изменены. С другой стороны, указатель curErr
имеет простой, неконстантный тип int
. Указатель curErr
можно использовать для изменения значения переменной errNumb
:
*pip = 2.72; //
//
//
if (*curErr) {
errorHandler();
*curErr = 0; //
//
}
Упражнение 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;
Как уже упоминалось, указатель — это объект, способный указывать на другой объект. В результате можно сразу сказать, является ли указатель сам константой и являются ли константой объекты, на которые он может указывать. Термин const
верхнего уровняconst
) используется для обозначения того ключевого слова const
, которое объявляет константой сам указатель. Когда указатель способен указывать на константный объект, это называется const
нижнего уровняconst
).
В более общем смысле спецификатор const
верхнего уровня означает, что объект сам константа. Спецификатор const
верхнего уровня может присутствовать в любом типе объекта, будь то один из встроенных арифметических типов, тип класса или ссылочный тип. Спецификатор const
нижнего уровня присутствует в базовом типе составных типов, таких как указатели или ссылки. Обратите внимание, что ссылочные типы, в отличие от большинства других типов, способны иметь спецификаторы const
как верхнего, так и нижнего уровня, независимо друг от друга.
int i = 0;
int *const pi = &i //
//
const int ci = 42; //
const int *p2 = &ci //
const int *const p3 = p2; //
const int &r = ci; //
Различие между спецификаторами
const
верхнего и нижнего уровней проявляется при копировании объекта. При копировании объекта спецификатор const
верхнего уровня игнорируется.
i = ci; //