Назад к вопросам
Middle
110
questionbank
Как работает счетчик ссылок в std::shared_ptr?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Счетчик ссылок в std::shared_ptr хранится в отдельном объекте — блоке управления (control block).
Блок управления создается:
- При первом создании
std::shared_ptrиз указателя. - При создании
std::shared_ptrс пользовательским удалителем или аллокатором. - При использовании
std::make_sharedилиstd::allocate_shared.
Этот блок управления содержит как минимум два счетчика:
- Счетчик сильных ссылок (strong count): Увеличивается при создании или копировании
std::shared_ptr. Уменьшается при уничтоженииstd::shared_ptr. Когда этот счетчик становится нулем, освобождается управляемый объект. - Счетчик слабых ссылок (weak count): Увеличивается при создании
std::weak_ptrизstd::shared_ptr. Уменьшается при уничтоженииstd::weak_ptr. Блок управления освобождается, когда оба счетчика — сильных и слабых ссылок — становятся нулем.
Использование std::make_shared предпочтительнее прямого создания из new, так как оно может аллоцировать объект и блок управления одним блоком памяти, что улучшает производительность и уменьшает фрагментацию.
Счетчики атомарны, что делает std::shared_ptr безопасным для использования в многопоточных сценариях, хотя доступ к самому управляемому объекту не синхронизирован по умолчанию.
Пример:
#include <iostream>
#include <memory>
struct MyObject {
int data;
MyObject(int d) : data(d) {
std::cout << "MyObject(" << data << ") created\n";
}
~MyObject() {
std::cout << "MyObject(" << data << ") destroyed\n";
}
};
int main() {
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
// strong count: 1, weak count: 0
{
std::shared_ptr<MyObject> ptr2 = ptr1;
// strong count: 2, weak count: 0
std::weak_ptr<MyObject> weak_ptr = ptr1;
// strong count: 2, weak count: 1
if (auto locked_ptr = weak_ptr.lock()) {
// strong count: 3, weak count: 1 (внутри lock, временно)
std::cout << "Object data: " << locked_ptr->data << std::endl;
}
// strong count: 2, weak count: 1
} // ptr2 выходит из области видимости
// strong count: 1, weak count: 1
// Объект еще не уничтожен, так как strong count == 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// strong count: 1, weak count: 2
} // weak_ptr2 выходит из области видимости
// strong count: 1, weak count: 1
} // ptr1 выходит из области видимости
// strong count: 0, weak count: 1
// Объект уничтожается, так как strong count стал 0
// Блок управления остается до тех пор, пока weak count не станет 0