Sobes.tech
Middle

Na základě čeho mohou více objektů shared_ptr odkazovat na stejný ukazatel?

sobes.tech AI

Odpověď od AI

Několik objektů std::shared_ptr může odkazovat na stejný ukazatel díky přítomnosti řídicího bloku (control block).

Řídicí blok, který je spojen s řízeným objektem, obsahuje:

  • Počítadlo silných odkazů (strong reference count): Zvyšuje se při vytváření nového shared_ptr pro stejný objekt. Snižuje se při zániku shared_ptr. Když dosáhne nuly, odkazovaný objekt (ukazatel) je odstraněn.
  • Počítadlo slabých odkazů (weak reference count): Používá se pro std::weak_ptr. Zvyšuje se při vytváření weak_ptr z shared_ptr. Snižuje se při zániku weak_ptr. Když jsou oba počítadla nulová, řídicí blok je odstraněn.
  • Vlastní ukazatel na řízený objekt: Ne samotný datový ukazatel, ale ten, který je řízen blokem.

Když vytvoříte shared_ptr z existujícího shared_ptr (kopírování, přiřazení kopírováním), začnou používat stejný řídicí blok a počet silných odkazů v tomto bloku se zvýší.

Pří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() {
    // Vytvoření prvního shared_ptr.
    // Vytvoří se řídicí blok a objekt MyData.
    // Počítadla strong: 1, weak: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";

    // Vytvoření druhého shared_ptr z ptr1.
    // Používá stejný řídicí blok.
    // Počítadlo strong se zvýší 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";

    // Vytvoření třetího shared_ptr z ptr1.
    // Používá stejný řídicí blok.
    // Počítadlo strong se zvýší 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 << "Opouštění rozsahu.\n";
    // ptr3 opouští rozsah.
    // Počítadlo strong klesne na 2.
    // ptr2 opouští rozsah.
    // Počítadlo strong klesne na 1.
    // ptr1 opouští rozsah.
    // Počítadlo strong klesne na 0.
    // Objekt MyData je zničen.
    // Řídicí blok je odstraněn.
}

Každý objekt shared_ptr obsahuje svůj ukazatel na řídicí blok a svůj ukazatel na datový objekt. Při kopírování shared_ptr jsou kopírovány oba tyto ukazatele a počet silných odkazů v sdíleném řídicím bloku se zvyšuje. Tímto způsobem všechny shared_ptr odkazují na stejný řídicí blok, který sleduje počet vlastněných kopií a určuje okamžik uvolnění řízeného zdroje.