shared_ptr — это умный указатель, реализующий семантику владения разделяемым ресурсом. Он хранит указатель на объект и указатель на управляющий блок.
Управляющий блок содержит:
- Счетчик сильных ссылок (reference count).
- Счетчик слабых ссылок (weak count).
- Пользовательский функтор удаления (deleter), если задан.
- Пользовательский аллокатор, если задан.
- Указатель на хранимый объект (то же самое, что хранится в самом
shared_ptr).
Принцип работы:
- Создание: При создании первого
shared_ptr, указывающего на объект, создается управляющий блок, счетчики ссылок инициализируются: сильных — 1, слабых — 0.
c
- Копирование: При копировании
shared_ptr счетчик сильных ссылок в управляющем блоке увеличивается на 1.
c
- Присваивание: При присваивании
shared_ptr старому ресурсу Decrement-ится (уменьшается) счетчик сильных ссылок, а новому ресурсу Increment-ится (увеличивается).
c
- Удаление: При уничтожении
shared_ptr (например, выход из области видимости) счетчик сильных ссылок Decrement-ится.
c
- Освобождение ресурса: Когда счетчик сильных ссылок достигает нуля, ресурс (объект, на который указывает
shared_ptr) удаляется с использованием заданного функтора удаления (или delete по умолчанию).
- Освобождение управляющего блока: Управляющий блок освобождается, когда оба счетчика (сильных и слабых) достигают нуля.
Преимущества:
- Автоматическое управление памятью для разделяемых ресурсов.
- Безопасность от двойного освобождения.
- Поддержка пользовательских функторов удаления.
Недостатки:
- Циклические ссылки могут привести к утечкам памяти (решается с помощью
weak_ptr).
- Незначительное увеличение накладных расходов из-за управляющего блока и атомарных операций со счетчиками.
- Потокобезопасность операций со самим
shared_ptr (копирование, присваивание, изменение хранимого указателя), но не с объектом, на который он указывает.