Нулевой указатель
Ссылка всегда должна принадлежать какой-нибудь переменной. Строка int& r; заканчивается ошибкой declaration of reference variable 'r' requires an initializer (ссылке нужно начальное значение). А вот указатель не обязан никуда указывать. Для этого есть значение nullptr, нулевой указатель:
int* currentPlayer = nullptr;Оно полезно, когда «ничего» — один из возможных вариантов. Например, в игре указатель currentPlayer указывает на очки игрока, чей сейчас ход, а когда игра заканчивается, ходить уже некому. Указатель можно также перенаправить на другую переменную, чего ссылка не умеет: ссылка всегда принадлежит той переменной, с которой была создана.
#include <iostream>
int main() {
int anna = 0;
int peter = 0;
int* currentPlayer = &anna;
*currentPlayer = *currentPlayer + 5;
currentPlayer = &peter;
*currentPlayer = *currentPlayer + 3;
currentPlayer = nullptr;
std::cout << "Анна: " << anna << ", Тимур: " << peter << std::endl;
if (currentPlayer == nullptr) {
std::cout << "Игра окончена" << std::endl;
}
return 0;
}Это выводит:
Анна: 5, Тимур: 3
Игра оконченаОбратите внимание на разницу: currentPlayer = &peter; без звёздочки меняет то, куда указывает указатель. *currentPlayer = *currentPlayer + 3; со звёздочкой меняет переменную, на которую он указывает.
Читать или записывать через nullptr — это баг, потому что там нет никакой переменной. На вашем компьютере программа обычно падает, а в терминале появляется Segmentation fault. Здесь, в браузере, она может остановиться с ошибкой RuntimeError: unreachable или даже продолжить работу с бессмысленными значениями. Поэтому, если указатель может быть nullptr, всегда проверяйте его перед использованием:
if (currentPlayer != nullptr) {
std::cout << *currentPlayer << std::endl;
} else {
std::cout << "Никто не ходит" << std::endl;
}Указатель, которому вы не дали значения (int* p;), хранит случайный адрес, как неинициализированная переменная хранит мусор. Поэтому всегда задавайте указателю значение сразу: адрес переменной или nullptr.
Задание
- 1
Программа выводит
Очки: 12, а затем останавливается с ошибкой, потому что во второй разprintPointsполучаетnullptrи читает через него. Добавьте в функцию проверку: еслиpointsравноnullptr, функция выводитНикто не ходит, а иначе выводит очки, как раньше. Тогда программа выведетОчки: 12, а затемНикто не ходит. - 2
Теперь ходит Тимур. В конце
main(передreturn 0;) добавьте переменнуюpeterсо значением7, перенаправьте на неё указательcurrentPlayerи снова вызовитеprintPoints(currentPlayer). Программа выведетОчки: 12,Никто не ходитиОчки: 7.