Указатели с ключевыми словами const и volatile

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

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

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

Чтобы объявить объект, на который указывает указатель, или constvolatileиспользуйте объявление формы:

const char *cpch;
volatile char *vpch;

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

char * const pchc;
char * volatile pchv;

Язык C++ запрещает назначения, позволяющие изменять объект или указатель, объявленный как const. Такие присваивания могут удалить информацию, с которой был объявлен объект или указатель, и тем самым подменить смысл исходного объявления. Рассмотрим следующее объявление:

const char cch = 'A';
char ch = 'B';

Учитывая предыдущие объявления двух объектов (cchтипа const char и chтипа char), допустимы следующие объявления и инициализации:

const char *pch1 = &cch;
const char *const pch4 = &cch;
const char *pch5 = &ch;
char *pch6 = &ch;
char *const pch7 = &ch;
const char *const pch8 = &ch;

Следующие объявления и инициализации вызывают ошибки.

char *pch2 = &cch;   // Error
char *const pch3 = &cch;   // Error

В объявлении pch2 задается указатель, при помощи которого может быть изменен постоянный объект, поэтому это объявление запрещено. Объявление pch3 указывает, что указатель является константой, а не объектом; объявление запрещено по той же причине pch2 , что объявление запрещено.

В следующих восьми примерах демонстрируется присваивание через указатель и изменение значения указателя для приведенных выше объявлений. Здесь мы предполагаем, что инициализация указателей pch1pch8 была выполнена без ошибок.

*pch1 = 'A';  // Error: object declared const
pch1 = &ch;   // OK: pointer not declared const
*pch2 = 'A';  // OK: normal pointer
pch2 = &ch;   // OK: normal pointer
*pch3 = 'A';  // OK: object not declared const
pch3 = &ch;   // Error: pointer declared const
*pch4 = 'A';  // Error: object declared const
pch4 = &ch;   // Error: pointer declared const

Указатели, объявленные как volatileили как смесь const и volatile, подчиняются тем же правилам.

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

errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );

Предыдущая инструкция объявляет функцию, strcpy_s, где два из трех аргументов имеют указатель charтипа. Так как аргументы передаются по ссылке, а не по значению, функция может быть свободна для изменения обоих strDestination и strSource , если strSource они не были объявлены как const. Объявление как const гарантирует вызывающий strSource объект, который strSource не может быть изменен вызываемой функцией.

Примечание.

Так как существует стандартное преобразование из имени типа в имя* типа*const, оно является законным для передачи аргумента типа char *в strcpy_s. Однако обратное не верно; для удаления атрибута const из объекта или указателя не существует неявного преобразования.

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

// const_pointer.cpp
int *const cpObject = 0;
int *pObject;

int main() {
pObject = cpObject;
cpObject = pObject;   // C3892
}

В следующем примере показано, как объявить объект как const, когда имеется указатель на указатель на объект.

// const_pointer2.cpp
struct X {
   X(int i) : m_i(i) { }
   int m_i;
};

int main() {
   // correct
   const X cx(10);
   const X * pcx = &cx;
   const X ** ppcx = &pcx;

   // also correct
   X const cx2(20);
   X const * pcx2 = &cx2;
   X const ** ppcx2 = &pcx2;
}

См. также

Указателинеобработанных указателей