На основе чего несколько `shared_ptr` могут ссылаться на один и тот же объект?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Несколько shared_ptr могут ссылаться на один и тот же объект благодаря использованию управляющего блока (control block).
Этот управляющий блок хранится в динамической памяти и содержит:
- Счётчик сильных ссылок (strong reference count): Увеличивается при создании нового
shared_ptr, ссылающегося на объект, или при копировании существующегоshared_ptr. Уменьшается при уничтоженииshared_ptr. Когда счётчик сильных ссылок достигает нуля, объект, на который указываютshared_ptr, уничтожается. - Счётчик слабых ссылок (weak reference count): Увеличивается при создании
weak_ptrизshared_ptr. Уменьшается при уничтоженииweak_ptr. Управляющий блок уничтожается только тогда, когда оба счётчика (сильных и слабых ссылок) достигают нуля. - Указатель на объект (pointer to the data object): Сам адрес объекта в памяти.
- Указатель на функцию-деструктор (deleter): Необязательно, используется для кастомного удаления объекта.
- Указатель на аллокатор (allocator): Необязательно, используется, если при создании
shared_ptrуказывался кастомный аллокатор.
Когда создается первый shared_ptr для данного объекта, аллоцируется управляющий блок. Последующие shared_ptr, созданные либо копированием, либо из weak_ptr, используют уже существующий управляющий блок, увеличивая счётчик сильных ссылок. Благодаря этому все shared_ptr, указывающие на один объект, "знают" об общем ресурсе и о том, сколько еще shared_ptr им владеют.
Например:
#include <memory>
#include <iostream>
int main() {
struct MyObject {
MyObject() { std::cout << "MyObject created\n"; }
~MyObject() { std::cout << "MyObject destroyed\n"; }
};
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(); // Создается объект и управляющий блок. strong_count = 1
std::shared_ptr<MyObject> ptr2 = ptr1; // Копирование. strong_count увеличивается до 2
std::shared_ptr<MyObject> ptr3 = ptr1; // Копирование. strong_count увеличивается до 3
std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;
std::cout << "ptr3 use_count: " << ptr3.use_count() << std::endl;
// При выходе из области видимости ptr3
// strong_count уменьшается до 2
// При выходе из области видимости ptr2
// strong_count уменьшается до 1
// При выходе из области видимости ptr1
// strong_count уменьшается до 0. Объект уничтожается.
return 0;
}
Таким образом, управляющий блок служит центральным механизмом для отслеживания владения объектом и управления его временем жизни, позволяя нескольким shared_ptr безопасно ссылаться на один и тот же ресурс.