Sobes.tech
Назад к вопросам
Junior — Middle
86

Чем отличаются различные виды умных указателей и как выбрать подходящий в зависимости от ситуации?

Компании, где спрашивали
Открытые РешенияОткрытые Решения

Ответ от нейросети

sobes.tech AI

В C++ существуют разные виды умных указателей, которые помогают управлять временем жизни объектов и предотвращают утечки памяти:

  • std::unique_ptr — владеет объектом эксклюзивно. Объект удаляется, когда unique_ptr уничтожается. Нельзя копировать, можно только перемещать. Используется, когда нужен единственный владелец ресурса.

  • std::shared_ptr — разделяет владение объектом между несколькими указателями. Объект удаляется, когда последний shared_ptr уничтожается. Подходит, когда ресурс нужен нескольким владельцам.

  • std::weak_ptr — слабая ссылка на объект, управляемый shared_ptr. Не влияет на время жизни объекта, используется для предотвращения циклических ссылок и проверки, существует ли объект.

Выбор умного указателя зависит от ситуации:

  • Если объект должен иметь одного владельца — используйте unique_ptr.
  • Если объект должен разделяться между несколькими владельцами — shared_ptr.
  • Если нужно ссылаться на объект, не увеличивая счётчик ссылок (например, для кэширования или обратных ссылок) — weak_ptr.

Пример использования unique_ptr:

#include <memory>
#include <iostream>

struct Foo {
    Foo() { std::cout << "Foo создан\n"; }
    ~Foo() { std::cout << "Foo уничтожен\n"; }
};

int main() {
    std::unique_ptr<Foo> p1 = std::make_unique<Foo>();
    // std::unique_ptr<Foo> p2 = p1; // Ошибка компиляции
    std::unique_ptr<Foo> p2 = std::move(p1); // Передача владения
}

Пример shared_ptr и weak_ptr:

#include <memory>
#include <iostream>

struct Foo {
    ~Foo() { std::cout << "Foo уничтожен\n"; }
};

int main() {
    std::shared_ptr<Foo> sp1 = std::make_shared<Foo>();
    std::shared_ptr<Foo> sp2 = sp1; // общий владелец
    std::weak_ptr<Foo> wp = sp1; // слабая ссылка

    if (auto spt = wp.lock()) { // проверяем, существует ли объект
        std::cout << "Объект доступен\n";
    }
}