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

Как работает счетчик в shared_ptr?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

В std::shared_ptr используется два счетчика:

  1. Use count (Счетчик ссылок): Атомарный счетчик, который инкрементируется при создании новой копии shared_ptr, указывающей на тот же объект, и декрементируется при разрушении shared_ptr. Когда достигает нуля, объект, на который указывает shared_ptr, удаляется.
  2. Weak count (Счетчик слабых ссылок): Атомарный счетчик, который инкрементируется при создании std::weak_ptr из данного shared_ptr и декрементируется при разрушении weak_ptr. Когда достигает нуля, блок управления (control block), содержащий оба счетчика, удаляется.

Эти счетчики хранятся в отдельном блоке управления (control block), который выделяется динамически при первом создании shared_ptr для объекта. Control block также может содержать deleter и allocator для объекта.

Использование атомарных счетчиков обеспечивает потокобезопасность при копировании и разрушении shared_ptr из разных потоков. Однако сам доступ к объекту, на который указывает shared_ptr, не потокобезопасен, если объект не является таковым изначально.

// Пример демонстрирующий управление счетчиками
struct MyObject {
    int data;
    MyObject(int d) : data(d) { /* ... */ }
    ~MyObject() { /* ... */ } // Деструктор вызывается при use_count == 0
};

int main() {
    std::shared_ptr<MyObject> sp1 = std::make_shared<MyObject>(10);
    // use_count == 1, weak_count == 0

    std::shared_ptr<MyObject> sp2 = sp1;
    // use_count == 2, weak_count == 0

    std::weak_ptr<MyObject> wp1 = sp1;
    // use_count == 2, weak_count == 1

    sp1.reset();
    // use_count == 1, weak_count == 1 (объект еще жив)

    {
        std::shared_ptr<MyObject> sp3 = wp1.lock();
        // Объект все еще существует, sp3 создан
        // use_count == 2, weak_count == 1
    } // sp3 выходит из области видимости
    // use_count == 1, weak_count == 1

    sp2.reset();
    // use_count == 0, weak_count == 1 (объект удален!)

    wp1.reset(); // weak_ptr разрушен
    // use_count == 0, weak_count == 0 (control block удален)

    return 0;
}