Указатели в C++

Указатели в C++: адреса памяти, оператор взятия адреса (&), разыменование (*), арифметика указателей и типичные ошибки.

Указатель — переменная, которая хранит адрес в памяти другой переменной. Указатели дают прямой доступ к данным и позволяют эффективно передавать большие объекты.

Адреса и оператор &

Каждая переменная занимает место в памяти и имеет адрес. Оператор & возвращает этот адрес.

#include <iostream>

int main() {
    int x = 42;
    std::cout << "Значение: " << x << "\n";
    std::cout << "Адрес:    " << &x << "\n";   // например, 0x7ffee4b2c5ac
    return 0;
}

Вывод:

Значение: 42
Адрес:    0x7ffee4b2c5ac

Объявление и разыменование

Указатель объявляют со звёздочкой: int* p. Оператор * перед указателем — разыменование: читаем или пишем значение по адресу.

#include <iostream>

int main() {
    int x = 10;
    int* p = &x;       // p хранит адрес x

    std::cout << *p << "\n";   // 10 — читаем через указатель

    *p = 99;           // меняем x через указатель
    std::cout << x << "\n";    // 99 — x изменился!
    return 0;
}

Вывод:

10
99

Указатели на массивы

Имя массива — это указатель на его первый элемент. Можно перебирать массив через арифметику указателей.

#include <iostream>

int main() {
    int arr[3] = {10, 20, 30};
    int* p = arr;      // указатель на arr[0]

    std::cout << *p << "\n";       // 10
    std::cout << *(p + 1) << "\n"; // 20 — следующий элемент
    std::cout << *(p + 2) << "\n"; // 30
    return 0;
}

Вывод:

10
20
30

new и delete — динамическая память

new выделяет память в куче (heap) и возвращает указатель. delete освобождает её. Без delete — утечка памяти.

#include <iostream>

int main() {
    int* p = new int(7);      // выделяем и инициализируем
    std::cout << *p << "\n"; // 7

    delete p;                 // обязательно освобождаем!
    p = nullptr;              // обнуляем указатель

    // Динамический массив:
    int* arr = new int[5]{1, 2, 3, 4, 5};
    std::cout << arr[2] << "\n";  // 3
    delete[] arr;             // для массивов — delete[]
    return 0;
}

Вывод:

7
3

В современном C++ предпочитают умные указатели (std::unique_ptr, std::shared_ptr) вместо «голого» new/delete — они освобождают память автоматически.

Типичные ошибки

  • Висячий указатель — обращение к памяти после delete. После удаления всегда пишите p = nullptr.
  • Утечка памяти — забыли вызвать delete. Используйте умные указатели.
  • Нулевой указатель — разыменование nullptr вызывает падение программы.
  • delete[] vs delete — для массивов нужен delete[], иначе поведение не определено.

Коротко

  • &x — адрес переменной; int* p = &x — указатель хранит адрес.
  • *p — разыменование: читаем/пишем значение по адресу.
  • new выделяет память в куче; delete освобождает — всегда в паре.
  • Для массивов: new T[n] и delete[].
Проверьте себя
1. Что хранит указатель?
AЗначение переменной
BАдрес в памяти
CТип данных
DРазмер объекта
2. Как прочитать значение по указателю?
Ap.value
B*p
C&p
Dp->val
3. Чем отличается delete от delete[]?
AНет разницы
Bdelete[] нужен для массивов, выделенных через new[]
Cdelete[] быстрее
Ddelete[] удаляет и указатель
Поддержать проект