На основании чего несколько объектов shared_ptr могут ссылаться на один и тот же указатель?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Несколько объектов std::shared_ptr могут ссылаться на один и тот же указатель благодаря наличию блока управления (control block).
Блок управления, связанный с управляемым объектом, содержит:
- Счетчик сильных ссылок (strong reference count): Увеличивается при создании нового
shared_ptrдля того же объекта. Уменьшается при уничтоженииshared_ptr. Когда становится равным нулю, связанный объект (указатель) удаляется. - Счетчик слабых ссылок (weak reference count): Используется для
std::weak_ptr. Увеличивается при созданииweak_ptrизshared_ptr. Уменьшается при уничтоженииweak_ptr. Когда оба счетчика становятся равными нулю, блок управления удаляется. - Собственный указатель на управляемый объект: Не сам указатель данных, а тот, который управляется блоком.
Когда вы создаете shared_ptr из существующего shared_ptr (копирование, присваивание-копирование), они начинают использовать один и тот же блок управления, и счетчик сильных ссылок в этом блоке увеличивается.
Пример:
#include <memory>
#include <iostream>
struct MyData {
int value;
MyData(int v) : value(v) { std::cout << "MyData(" << value << ") created.\n"; }
~MyData() { std::cout << "MyData(" << value << ") destroyed.\n"; }
};
int main() {
// Создается первый shared_ptr.
// Создается блок управления и объект MyData.
// Счетчики strong: 1, weak: 0.
std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
// Создается второй shared_ptr из ptr1.
// Используется тот же блок управления.
// Счетчик strong увеличивается до 2.
std::shared_ptr<MyData> ptr2 = ptr1;
std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";
// Создается третий shared_ptr из ptr1.
// Используется тот же блок управления.
// Счетчик strong увеличивается до 3.
std::shared_ptr<MyData> ptr3 = ptr1;
std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";
std::cout << "ptr3 use count: " << ptr3.use_count() << "\n";
std::cout << "Leaving scope.\n";
// ptr3 выходит из области видимости.
// Счетчик strong уменьшается до 2.
// ptr2 выходит из области видимости.
// Счетчик strong уменьшается до 1.
// ptr1 выходит из области видимости.
// Счетчик strong уменьшается до 0.
// Объект MyData уничтожается.
// Блок управления уничтожается.
}
Каждый объект shared_ptr содержит свой указатель на блок управления и свой указатель на объект данных. При копировании shared_ptr копируются оба этих указателя, и дополнительно увеличивается счетчик сильных ссылок в общем блоке управления. Таким образом, все shared_ptr указывают на один и тот же блок управления, который отслеживает количество владеющих их копий и определяет момент уничтожения управляемого ресурса.