9.15 – Указатели и const

Добавлено 8 июня 2021 в 23:55
Глава 9 – Массивы, строки, указатели и ссылки  (содержание)

Указание на константные переменные

Пока что все указатели, которые вы видели, были неконстантными указателями на неконстантные значения:

int value{ 5 };
int* ptr{ &value };
*ptr = 6; // меняем value на 6

Однако что произойдет, если значение value будет константным?

const int value{ 5 }; // value - константа
int* ptr{ &value };   // ошибка компиляции: невозможно преобразовать const int* в int*
*ptr = 6;             // меняем value на 6

Приведенный выше фрагмент не будет компилироваться – мы не можем установить неконстантный указатель на константную переменную. В этом есть смысл: константная переменная – это переменная, значение которой нельзя изменить. Гипотетически, если бы мы могли установить неконстантный указатель на константное значение, тогда мы могли бы выполнить косвенное обращение через неконстантный указатель и изменить значение. Это нарушит назначение const.

Указатель на константное значение

Указатель на константное значение – это (неконстантный) указатель, указывающий на константное значение.

Чтобы объявить указатель на константное значение, используйте ключевое слово const перед типом данных:

const int value{ 5 };
const int* ptr{ &value }; // это нормально, ptr - это неконстантный указатель,
                          // указывающий на "const int"
*ptr = 6; // не допускается, мы не можем изменить константное значение

В приведенном выше примере ptr указывает на const int.

Пока всё хорошо, правда? Теперь рассмотрим следующий пример:

int value{ 5 };           // value - не константа
const int* ptr{ &value }; // это всё еще нормально

Указатель на константную переменную может указывать на неконстантную переменную (например, переменная value в приведенном выше примере). Подумайте об этом так: указатель на константную переменную обрабатывает переменную как константу, когда к ней обращаются через указатель, независимо от того, была ли переменная изначально определена как константа или нет.

Таким образом, допустимо следующее:

int value{ 5 };
const int* ptr{ &value }; // ptr указывает на "const int"
value = 6; // value не является константой при
           // доступе через неконстантный идентификатор

Но недопустимо следующее:

int value{ 5 };
const int* ptr{ &value }; // ptr указывает на "const int"
*ptr = 6; // ptr рассматривает свое значение как const,
          // поэтому изменение value через ptr недопустимо

Поскольку указатель на константное значение сам по себе не является константой (он просто указывает на константное значение), указатель может быть перенаправлен на другие значения:

int value1{ 5 };
const int *ptr{ &value1 }; // ptr указывает на const int
 
int value2{ 6 };
ptr = &value2; // нормально, теперь ptr указывает на другой const int

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

Мы также можем сделать сам указатель константным. Константный указатель – это указатель, значение которого не может быть изменено после инициализации.

Чтобы объявить константный указатель, используйте ключевое слово const между звездочкой и именем указателя:

int value{ 5 };
int* const ptr{ &value };

Как и обычная константная переменная, константный указатель должен быть инициализирован значением при объявлении. Это означает, что константный указатель всегда будет указывать на один и тот же адрес. В приведенном выше случае ptr всегда будет указывать на адрес value (пока ptr не выйдет из области видимости и не будет уничтожен).

int value1{ 5 };
int value2{ 6 };
 
int* const ptr{ &value1 }; // хорошо, константный указатель инициализируется адресом value1
ptr = &value2; // недопустимо, после инициализации константный указатель изменить нельзя

Однако, поскольку значение, на которое указывается, всё еще не является константой, его можно изменить с помощью косвенного обращения через константный указатель:

int value{ 5 };
int* const ptr{ &value }; // ptr всегда будет указывать на value
*ptr = 6; // разрешено, поскольку ptr указывает на неконстантный int

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

Наконец, можно объявить константный указатель на константное значение, используя ключевое слово const и перед типом, и перед именем переменной:

int value{ 5 };
const int* const ptr{ &value };

Константный указатель на константное значение нельзя установить так, чтобы он указывал на другой адрес, а также нельзя изменить значение, на которое он указывает, с помощью косвенного обращения через указатель.

Резюме

Подводя итог, вам нужно запомнить всего 4 правила, и они довольно логичны:

  • Неконстантный указатель может быть перенаправлен на другие адреса.
  • Константный указатель всегда указывает на один и тот же адрес, и этот адрес нельзя изменить.
  • Указатель на неконстантное значение может изменить значение, на которое он указывает. Он не может указывать на константное значение.
  • Указатель на константное значение обрабатывает значение как const (даже если это не так) и, следовательно, не может изменить значение, на которое он указывает.

Сохранение правильного синтаксиса объявления может быть сложной задачей. Просто помните, что тип значения, на который указывает указатель, всегда находится в самом левом краю:

int value{ 5 };

// ptr1 указывает на "const int", поэтому это указатель на константное значение
const int* ptr1{ &value };

// ptr2 указывает на "int", поэтому это константный указатель на неконстантное значение.
int* const ptr2{ &value }; 

// ptr3 указывает на "const int", поэтому это константный указатель на константное значение.
const int* const ptr3{ &value };

Заключение

Указатели на константные значения в основном используются в параметрах функций (например, при передаче массива в функцию), чтобы гарантировать, что функция случайно не изменит переданный аргумент. Мы обсудим это далее в разделе, посвященном функциям.

Теги

C++ / CppconstLearnCppДля начинающихКонстантаОбучениеПрограммированиеУказатель / Pointer (программирование)

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.