Sobes.tech
Middle

std::shared_ptr'da referanslar soni qanday ishlaydi?

sobes.tech AI

AIdan javob

std::shared_ptr ichidagi referanslar soni alohida obyektda saqlanadi: nazorat blokida (control block).

Bu nazorat bloki quyidagi holatlarda yaratiladi:

  • Birinchi marta std::shared_ptr ni ko‘rsatkichdan yaratishda.
  • Maxsus o‘chirishchi yoki ajratuvchi bilan std::shared_ptr ni yaratishda.
  • std::make_shared yoki std::allocate_shared ishlatilganda.

Ushbu nazorat bloki kamida ikki hisoblagichni o‘z ichiga oladi:

  1. Kuchli referanslar hisoblagichi (strong count): std::shared_ptr yaratilganda yoki nusxa ko‘chirganda oshadi. std::shared_ptr yo‘q qilinayotganda kamayadi. Bu hisoblagich nolga teng bo‘lsa, boshqarilayotgan obyekt bo‘shatiladi.
  2. Zaif referanslar hisoblagichi (weak count): std::shared_ptr dan std::weak_ptr yaratilganda oshadi. std::weak_ptr yo‘q qilinayotganda kamayadi. Ikkala hisoblagich — kuchli va zaif — nolga teng bo‘lsa, nazorat bloki bo‘shatiladi.

std::make_shared dan foydalanish to‘g‘ridan-to‘g‘ri new bilan yaratishga nisbatan afzaldir, chunki u obyekt va nazorat blokini bitta xotira blokida ajratishi mumkin, bu esa ishlash tezligini oshiradi va bo‘linishni kamaytiradi.

Hisoblagichlar atomik bo‘lib, std::shared_ptr ko‘p ipli muhitda xavfsiz foydalanishni ta’minlaydi, garchi boshqarilayotgan obyektga kirish odatda sinxronlashtirilmagan.

Misol:

#include <iostream>
#include <memory>

struct MyObject {
    int data;
    MyObject(int d) : data(d) {
        std::cout << "MyObject(" << data << ") yaratildi\n";
    }
    ~MyObject() {
        std::cout << "MyObject(" << data << ") yo‘q qilindi\n";
    }
};

int main() {
    std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
    // kuchli hisoblagich: 1, zaif hisoblagich: 0

    {
        std::shared_ptr<MyObject> ptr2 = ptr1;
        // kuchli hisoblagich: 2, zaif hisoblagich: 0

        std::weak_ptr<MyObject> weak_ptr = ptr1;
        // kuchli hisoblagich: 2, zaif hisoblagich: 1

        if (auto locked_ptr = weak_ptr.lock()) {
            // kuchli hisoblagich: 3, zaif hisoblagich: 1 (vaqtinchalik lock ichida)
            std::cout << "Obyekt ma'lumotlari: " << locked_ptr->data << std::endl;
        }
        // kuchli hisoblagich: 2, zaif hisoblagich: 1
    } // ptr2 scope dan chiqadi
    // kuchli hisoblagich: 1, zaif hisoblagich: 1

    // Ob'ekt hali yo‘q qilinmagan, chunki kuchli hisoblagich == 1

    {
        std::weak_ptr<MyObject> weak_ptr2 = ptr1;
        // kuchli hisoblagich: 1, zaif hisoblagich: 2
    } // weak_ptr2 scope dan chiqadi
    // kuchli hisoblagich: 1, zaif hisoblagich: 1

} // ptr1 scope dan chiqadi
// kuchli hisoblagich: 0, zaif hisoblagich: 1
// Ob'ekt yo‘q qilinadi, chunki kuchli hisoblagich 0 ga teng
// Nazorat bloki zaif hisoblagich 0 bo‘lgach, ochiriladi