Назад к вопросам
Junior
94
questionbank

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