Ключевое слово const может добавляться к описанию объекта, чтобы сделать этот объект константой, а не переменной. Например:
const int model = 145; const int v[] = (* 1, 2, 3, 4 *);
Поскольку константе ничего нельзя присвоить, она должна быть инициализирована. Описание чего-нибудь как const гарантирует, что его значение не изменится в области видимости:
model = 145; // ошибка model++; // ошибка
Заметьте, что const изменяет тип, то есть ограничивает способ использования объекта, вместо того, чтобы задавать способ размещения константы. Поэтому например вполне разумно, а иногда и полезно, описывать функцию как возвращающую const:
const char* peek(int i) (* return private[i]; *)
Функцию вроде этой можно было бы использовать для того, чтобы давать кому-нибудь читать строку, которая не может быть затерта или переписана (этим кем-то).
С другой стороны, компилятор может несколькими путями воспользоваться тем, что объект является константой (конечно, в зависимости от того, насколько он сообразителен). Самое очевидное – это то, что для константы не требуется выделять память, поскольку компилятор знает ее значение. Кроме того, инициализатор константы часто (но не всегда) является константным выражением, то есть он может быть вычислен на стадии компиляции. Однако для вектора констант обычно приходится выделять память, поскольку компилятор в общем случае не может вычислить, на какие элементы вектора сделаны ссылки в выражениях. Однако на многих машинах даже в этом случае может достигаться повышение эффективности путем размещения векторов констант в память, доступную только для чтения.
Использование указателя вовлекает два объекта: сам указатель и указываемый объект. Снабжение описания указателя «префиксом» const делает объект, но не сам указатель, константой. Например:
const char* pc = «asdf»; // указатель на константу pc[3] = 'a'; // ошибка pc = «ghjk»; // ok
Чтобы описать сам const указатель, а не указываемый объект, как константный, используется операция const*. Например:
char *const cp = «asdf»; // константный указатель cp[3] = 'a'; // ok cp = «ghjk»; // ошибка
Чтобы сделать константами оба объекта, их оба нужно описать const. Например:
const char *const cpc = «asdf»; // const указатель на const cpc[3] = 'a'; // ошибка cpc = «ghjk»; // ошибка
Объект, являющийся константой при доступе к нему через один указатель, может быть переменной, когда доступ осуществляется другими путями. Это в частности полезно для параметров функции. Посредством описания параметра указателя как const функции запрещается изменять объект, на который он указывает. Например:
char* strcpy(char* p, const char* q); // не может изменить q
Указателю на константу можно присваивать адрес переменой, поскольку никакого вреда от этого быть не может. Однако нельзя присвоить адрес константы указателю, на который не было наложено ограничение, поскольку это позволило бы изменить значение объекта. Например:
int a = 1; const c = 2; const* p1 = amp;c; // ok const* p2 = amp;a; // ok int* p3 = amp;c; // ошибка *p3 = 7; // меняет значение c
Как обычно, если тип в описании опущен, то он предполагается int.