Какие виды указателей в C++ ты знаешь?

«Какие виды указателей в C++ ты знаешь?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В C++ указатели — это мощный, но требующий аккуратности инструмент для работы с памятью и полиморфизмом. Вот их основные виды:

*1. Сырые (raw) указатели (`T`):** Базовый тип, хранящий адрес памяти. Не управляют временем жизни объекта.

int value = 10;
int* raw_ptr = &value; // Указатель на int
*raw_ptr = 20; // Разыменование и изменение значения

2. Умные указатели (smart pointers): Классы из <memory>, которые автоматически управляют временем жизни динамически выделенных объектов.

  • std::unique_ptr<T>: Выражает эксклюзивное владение. Невозможно скопировать, только переместить. Объект уничтожается при разрушении unique_ptr. Идеален для владения ресурсом в области видимости.
    auto uptr = std::make_unique<MyClass>(args); // Предпочтительный способ создания
    // uptr автоматически удалит объект при выходе из области видимости
  • std::shared_ptr<T>: Разделяемое владение с подсчетом ссылок (reference counting). Объект уничтожается, когда последний shared_ptr на него разрушается.
    auto sptr1 = std::make_shared<MyClass>();
    auto sptr2 = sptr1; // Оба shared_ptr владеют одним объектом
  • std::weak_ptr<T>: «Слабая» ссылка на объект, управляемый shared_ptr. Не увеличивает счетчик ссылок. Используется для разрыва циклических зависимостей и безопасного доступа к объекту, который может быть уже удален.
    std::weak_ptr<MyClass> wptr = sptr1;
    if (auto temp_ptr = wptr.lock()) { // Попытка получить shared_ptr
        // Объект еще жив, можно использовать temp_ptr
    }

3. Указатели на функции и члены класса:

  • Указатель на функцию: ReturnType (*func_ptr)(ParamTypes) = &function_name;
  • Указатель на член данных: Type ClassName::*ptr = &ClassName::member;
  • Указатель на метод: ReturnType (ClassName::*method_ptr)(Params) = &ClassName::method;

4. Ссылки (T& и const T&): Хотя технически это не указатели, они семантически похожи на константные указатели, которые всегда разыменованы и не могут быть null. Более безопасная альтернатива указателям, когда null-значение не требуется.

Правило сегодняшнего дня: В современном C++ сырые указатели следует использовать только для наблюдения (non-owning pointers), без передачи владения. Все владение динамической памятью должно быть выражено через умные указатели (unique_ptr по умолчанию, shared_ptr при необходимости разделяемого владения). Это предотвращает утечки памяти и ошибки двойного удаления.