Указатели в C++ без паники

Указатели в C++ пугают почти всех. И это нормально: до этого переменная была просто коробкой со значением, а теперь появляется адрес в памяти, &, *, nullptr и ощущение, что один неверный символ сломает программу

Начнем аккуратно. Указатель — это переменная, которая хранит адрес другой переменной

Адрес переменной

#include <iostream>

int main() {
    int age = 25;

    std::cout << age << std::endl;
    std::cout << &age << std::endl;

    return 0;
}

age — значение

&age — адрес переменной в памяти

Адрес может выглядеть странно:

0x7ff7b2c...

Точное значение не важно. Важно понять: переменная где-то лежит в памяти, и у этого места есть адрес

Первый указатель

#include <iostream>

int main() {
    int age = 25;
    int* pointerToAge = &age;

    std::cout << pointerToAge << std::endl;
    std::cout << *pointerToAge << std::endl;

    return 0;
}

int* pointerToAge — указатель на int

&age — адрес переменной age

*pointerToAge — значение по адресу, который хранит указатель

Можно читать так:

  • pointerToAge хранит адрес;
  • *pointerToAge достает значение по адресу.

Меняем значение через указатель

#include <iostream>

int main() {
    int age = 25;
    int* pointerToAge = &age;

    *pointerToAge = 30;

    std::cout << age << std::endl;

    return 0;
}

Вывод будет:

30

Мы изменили age не напрямую, а через указатель

nullptr

Указатель может никуда не указывать:

int* pointer = nullptr;

Перед использованием такой указатель нужно проверить:

if (pointer != nullptr) {
    std::cout << *pointer << std::endl;
}

Разыменование nullptr — плохая идея. Программа может упасть

Указатель и массив

В C++ массивы тесно связаны с адресами

#include <iostream>

int main() {
    int scores[3] = {8, 9, 10};

    std::cout << scores[0] << std::endl;
    std::cout << *(scores + 0) << std::endl;
    std::cout << *(scores + 1) << std::endl;

    return 0;
}

scores в таком контексте ведет себя как адрес первого элемента. scores + 1 — адрес следующего элемента

Это помогает понять низкий уровень, но в обычном учебном коде лучше не злоупотреблять арифметикой указателей

Зачем указатели вообще нужны

Указатели нужны для:

  • работы с памятью;
  • передачи адреса в функцию;
  • низкоуровневого кода;
  • взаимодействия с C-библиотеками;
  • динамических структур данных;
  • понимания массивов и строк старого C-стиля.

В современном C++ часто стараются использовать более безопасные инструменты:

  • ссылки;
  • std::vector;
  • std::string;
  • умные указатели;
  • RAII.

Но базовое понимание обычных указателей все равно важно

Ссылка как мягкий сосед указателя

Ссылка:

int age = 25;
int& ref = age;

ref = 30;

Теперь age тоже станет 30. Ссылка похожа на другое имя для переменной. Она проще для первого понимания передачи в функцию

void increase(int& value) {
    value++;
}

Указатели дают больше свободы, но и больше ответственности

Частые ошибки

Разыменование nullptr

int* pointer = nullptr;
std::cout << *pointer << std::endl;

Так делать нельзя

Указатель без инициализации

int* pointer;
std::cout << *pointer << std::endl;

В указателе мусорный адрес. Инициализируй:

int* pointer = nullptr;

Путаница & и *

&value берет адрес

*pointer берет значение по адресу

Возврат адреса локальной переменной

int* createValue() {
    int value = 10;
    return &value;
}

Так нельзя. Локальная переменная исчезнет после выхода из функции

Мини-задание

  1. Создай переменную score.
  2. Создай указатель на нее.
  3. Выведи адрес.
  4. Выведи значение через указатель.
  5. Измени значение через указатель.

Пример:

#include <iostream>

int main() {
    int score = 10;
    int* scorePointer = &score;

    std::cout << "Адрес: " << scorePointer << std::endl;
    std::cout << "Значение: " << *scorePointer << std::endl;

    *scorePointer = 15;

    std::cout << "Новое значение: " << score << std::endl;

    return 0;
}

Ответы на эти вопросы могут быть для вас полезными

Что такое указатель в C++?

Это переменная, которая хранит адрес другой переменной

Что делает &?

Оператор & получает адрес переменной

Что делает *?

В объявлении int означает тип указателя. Перед именем указателя, например ptr, получает значение по адресу

Что такое nullptr?

Это значение указателя, который никуда не указывает. Его используют вместо старого NULL

Нужно ли новичку сразу глубоко учить указатели?

Нет. Сначала достаточно понять адрес, разыменование, nullptr и связь с массивами. Глубокую динамическую память лучше изучать постепенно

Что почитать дальше по C++

Чтобы тема складывалась в понятный маршрут, рядом лучше открыть:

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x