Sobes.tech
Middle

Na základe čoho môžu viaceré objekty shared_ptr odkazovať na ten istý ukazovateľ?

sobes.tech AI

Odpoveď od AI

Niekoľko objektov std::shared_ptr môže odkazovať na rovnaký ukazovateľ vďaka prítomnosti riadiaceho bloku (control block).

Riadiaci blok, ktorý je spojený s riadeným objektom, obsahuje:

  • Počítadlo silných odkazov (strong reference count): Zvyšuje sa pri vytváraní nového shared_ptr pre ten istý objekt. Znižuje sa pri zániku shared_ptr. Keď dosiahne nulu, spojený objekt (ukazovateľ) sa odstráni.
  • Počítadlo slabých odkazov (weak reference count): Používa sa pre std::weak_ptr. Zvyšuje sa pri vytváraní weak_ptr z shared_ptr. Znižuje sa pri zániku weak_ptr. Keď sú oba počítadlá nulové, riadiaci blok sa odstráni.
  • Vlastný ukazovateľ na riadený objekt: Nie samotný ukazovateľ na údaje, ale ten, ktorý je riadený blokom.

Keď vytvoríte shared_ptr z existujúceho shared_ptr (kopírovanie, priradenie kopírovaním), začnú používať ten istý riadiaci blok a počet silných odkazov v tomto bloku sa zvýši.

Príklad:

#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() {
    // Vytvorenie prvého shared_ptr.
    // Vytvorí sa riadiaci blok a objekt MyData.
    // Počítadlo silných: 1, slabých: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";

    // Vytvorenie druhého shared_ptr z ptr1.
    // Používa ten istý riadiaci blok.
    // Počítadlo silných sa zvýši na 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";

    // Vytvorenie tretieho shared_ptr z ptr1.
    // Používa ten istý riadiaci blok.
    // Počítadlo silných sa zvýši na 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 << "Opúšťanie rozsahu.\n";
    // ptr3 opúšťa rozsah.
    // Počítadlo silných sa zníži na 2.
    // ptr2 opúšťa rozsah.
    // Počítadlo silných sa zníži na 1.
    // ptr1 opúšťa rozsah.
    // Počítadlo silných sa zníži na 0.
    // Objekt MyData sa zničí.
    // Riadiaci blok sa odstráni.
}

Každý objekt shared_ptr obsahuje svoj ukazovateľ na riadiaci blok a svoj ukazovateľ na dátový objekt. Pri kopírovaní shared_ptr sa kopírujú oba tieto ukazovatele a počet silných odkazov v spoločnom riadiacom bloku sa zvýši. Takto všetky shared_ptr ukazujú na ten istý riadiaci blok, ktorý sleduje počet vlastníckych kópií a určuje okamih uvoľnenia riadeného zdroja.