Назад к вопросам
Middle
92
questionbank

На основании чего несколько объектов 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 указывают на один и тот же блок управления, который отслеживает количество владеющих их копий и определяет момент уничтожения управляемого ресурса.