// выводит 42
Обращение к значению указателя возвращает объект, на который указывает указатель. Присвоив значение результату оператора обращения к значению, можно присвоить его самому объекту.
*p = 0; // * возвращает объект; присвоение нового значения
// ival через указатель p
cout << *p; // выводит 0
При присвоении значения *p
оно присваивается объекту, на который указывает указатель p
.
Обратиться к значению можно только по допустимому указателю, который указывает на объект.
Некоторые символы, такие как &
и *
, используются и как оператор в выражении, и как часть объявления. Контекст, в котором используется символ, определяет то, что он означает.
int i = 42;
int &r = i; // & следует за типом в части объявления; r - ссылка
int *p; // * следует за типом в части объявления; p - указатель
p = &i; // & используется в выражении как оператор
// обращения к адресу
*p = i; // * используется в выражении как оператор
// обращения к значению
int &r2 = *p; // & в части объявления; * - оператор обращения к значению
В объявлениях символы &
и *
используются для формирования составных типов. В выражениях эти же символы используются для обозначения оператора. Поскольку тот же символ используется в совершенно ином смысле, возможно, стоит игнорировать внешнее сходство и считать их как будто различными символами.
Нулевой указатель (null pointer) не указывает ни на какой объект. Код может проверить, не является ли указатель нулевым, прежде чем пытаться использовать его. Есть несколько способов получить нулевой указатель.
int *p1 = nullptr; // эквивалентно int *p1 = 0;
int *p2 = 0; // непосредственно инициализирует p2 литеральной
// константой 0, необходимо #include cstdlib
int *p3 = NULL; // эквивалентно int *p3 = 0;
Проще всего инициализировать указатель, используя литерал nullptr
, который был введен новым стандартом. Литерал nullptr
имеет специальный тип, который может быть преобразован (см. раздел 2.1.2) в любой другой ссылочный тип. В качестве альтернативы можно инициализировать указатель литералом 0
, как это сделано в определении указателя p2
.
Программисты со стажем иногда используют переменную препроцессора (preprocessor variable) NULL
, которую заголовок cstdlib
определяет как 0
.
Немного подробней препроцессор рассматривается в разделе 2.6.3, а пока достаточно знать, что препроцессор (preprocessor) — это программа, которая выполняется перед компилятором. Переменные препроцессора используются препроцессором, они не являются частью пространства имен std
, поэтому их указывают непосредственно, без префикса std::
.
При использовании переменной препроцессора последний автоматически заменяет такую переменную ее значением. Следовательно, инициализация указателя переменной NULL
эквивалентна его инициализации значением 0
. Сейчас программы С++ вообще должны избегать применения переменной NULL
и использовать вместо нее литерал nullptr
.
Нельзя присваивать переменную типа int
указателю, даже если ее значением является 0
.
int zero = 0;
pi = zero; // ошибка: нельзя присвоить переменную типа int указателю
Неинициализированные указатели — обычный источник ошибок времени выполнения.
Подобно любой другой неинициализированной переменной, последствия использования неинициализированного указателя непредсказуемы. Использование неинициализированного указателя почти всегда приводит к аварийному отказу во время выполнения. Однако поиск причин таких отказов может оказаться на удивление трудным.