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_ptrpre ten istý objekt. Znižuje sa pri zánikushared_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_ptrzshared_ptr. Znižuje sa pri zánikuweak_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.