Перейти к содержимому
Теория · Ссылки и указатели · урок 5 из 8

const T* и T* const

Переменная a в этой программе объявлена без const, и всё же изменить её через указатель p компилятор не даёт:

C++
int main() {
    int a = 1;
    int b = 2;
    const int* p = &a;
    *p = 5;  // ✗
    p = &b;
    return *p;
}
TEXT
error: read-only variable is not assignable

Ошибка только в строке *p = 5;, а строка p = &b; компилируется. Что запрещает const в объявлении указателя, зависит от того, где он стоит.

Указатель на константу

const int* p — указатель на константу (pointer to const). Через него значение можно читать, но нельзя менять. Указывать он может и на переменную без const: запрет действует только на запись через p, а a = 5; по-прежнему работает. Сам p — обычная переменная, поэтому его можно перенаправить, как в строке p = &b;.

Функция, которая только читает числа по указателю, объявляет параметр как const int* data. Такое объявление обещает, что функция не изменит числа. Случайную запись вроде data[0] = 0; в теле функции компилятор остановит той же ошибкой, что и *p = 5;. Так компилятор следит, чтобы функция не изменила числа вызывающего кода.

Константный указатель

Если const стоит после *, постоянным становится сам указатель. int* const q — константный указатель (const pointer): перенаправить его нельзя, поэтому инициализируют его сразу. Зато значение через q менять можно. В const int* const r запрещено и то и другое.

C++
#include <iostream>

int main() {
    int a = 1;
    int b = 2;
    const int* p = &a;
    p = &b;
    int* const q = &a;
    *q = 5;
    std::cout << *p << ' ' << a << '\n';  // 2 5
}

Всё решает место const относительно *: слева от звёздочки он относится к значению, а справа — к самому указателю. Поэтому int const* p значит то же, что const int* p.

Объявление удобно читать справа налево, начиная с имени. int* const q — «q — константный указатель на int». const int* p — «p — указатель на int, который const».

Частая ошибка

Адрес const-переменной кладут в обычный указатель:

C++
int main() {
    const int limit = 10;
    int* p = &limit;  // ✗
    return *p;
}
TEXT
error: cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'

Через int* значение limit можно было бы изменить, поэтому компилятор запрещает такую инициализацию. Объявите указатель как const int* p = &limit;.