← Назад к вопросам

Что такое shared_ptr?

1.0 Junior🔥 251 комментариев
#Умные указатели и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

shared_ptr в C++

shared_ptr — это один из наиболее важных инструментов современного C++ для управления динамической памятью. Это умный указатель из стандартной библиотеки, реализующий концепцию разделяемого владения памятью.

Что такое shared_ptr?

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

Как это работает?

#include <memory>

// Создание shared_ptr
std::shared_ptr<int> ptr1(new int(42));
std::shared_ptr<int> ptr2 = ptr1;  // Копирование
std::shared_ptr<int> ptr3 = std::make_shared<int>(42);  // Лучший способ

// Счётчик ссылок = 3 (ptr1, ptr2, ptr3)

ptr1.reset();  // Счётчик = 2
// Объект удаляется только когда счётчик = 0

Ключевые особенности

  1. Автоматическое управление памятью — нет необходимости вызывать delete
  2. Подсчёт ссылок — отслеживает количество владельцев объекта
  3. Безопасность — предотвращает утечки памяти
  4. RAII паттерн — Resource Acquisition Is Initialization
  5. Потокобезопасность (частичная) — счётчик ссылок потокобезопасен, но доступ к объекту нет

Работа со счётчиком ссылок

std::shared_ptr<int> ptr = std::make_shared<int>(10);

std::cout << ptr.use_count();  // 1

{
    std::shared_ptr<int> ptr2 = ptr;
    std::cout << ptr.use_count();  // 2
}  // ptr2 выходит из области видимости

std::cout << ptr.use_count();  // 1
// Объект остаётся в памяти

ptr = nullptr;  // или ptr.reset()
// Счётчик = 0, объект удаляется

Практические примеры

Управление ресурсами:

class Resource {
public:
    Resource() { std::cout << "Created\n"; }
    ~Resource() { std::cout << "Destroyed\n"; }
};

std::shared_ptr<Resource> ptr = std::make_shared<Resource>();
// Вывод: Created
// При выходе из области видимости: Destroyed

В контейнерах:

std::vector<std::shared_ptr<Resource>> vec;
vec.push_back(std::make_shared<Resource>());
vec.push_back(std::make_shared<Resource>());
// Объекты автоматически удалятся при очистке вектора

В сложных структурах данных:

struct Node {
    int data;
    std::shared_ptr<Node> next;
};

std::shared_ptr<Node> head = std::make_shared<Node>();
head->next = std::make_shared<Node>();
// Циклические ссылки могут привести к утечке!

Важные правила использования

  1. Используй make_shared — более эффективно и безопаснее:
// Хорошо
std::shared_ptr<int> ptr = std::make_shared<int>(42);

// Менее эффективно
std::shared_ptr<int> ptr(new int(42));
  1. Не создавай циклические ссылки — используй weak_ptr:
struct Node {
    int data;
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;  // Слабая ссылка!
};
  1. Не передавай this как shared_ptr — используй enable_shared_from_this:
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    std::shared_ptr<MyClass> getShared() {
        return shared_from_this();
    }
};

shared_ptr vs unique_ptr

Параметрshared_ptrunique_ptr
ВладениеРазделяемоеИсключительное
КопированиеДопускаетсяЗапрещено
ПроизводительностьМедленнее (счётчик)Быстрее
ИспользованиеСложные структурыПростое владение
ПотокобезопасностьЧастичнаяНет

Преимущества и недостатки

Преимущества:

  • Автоматическое управление памятью
  • Простота использования
  • Предотвращение утечек памяти
  • Гибкость (несколько владельцев)

Недостатки:

  • Издержки памяти на подсчёт ссылок
  • Небольшие издержки производительности
  • Риск циклических ссылок
  • Некоторая непредсказуемость удаления объекта

Вывод

shared_ptr — это мощный инструмент для безопасного управления памятью в C++11 и новее. Он значительно упрощает разработку, но требует понимания механизма подсчёта ссылок и потенциальных проблем с циклическими ссылками. Для большинства задач modern C++ рекомендуется использовать shared_ptr или unique_ptr вместо ручного управления памятью.