Middle
Ako funguje čítač odkazov v std::shared_ptr?
sobes.tech AI
Odpoveď od AI
Počítadlo odkazov v std::shared_ptr sa uchováva v samostatnom objekte — riadiacom bloku.
Riadiaci blok sa vytvára:
- Pri prvom vytvorení
std::shared_ptrz ukazovateľa. - Pri vytvorení
std::shared_ptrs používateľským vymazávačom alebo alokátorom. - Pri použití
std::make_sharedalebostd::allocate_shared.
Tento riadiaci blok obsahuje aspoň dva počítadlá:
- Počítadlo silných odkazov (strong count): Zvyšuje sa pri vytvorení alebo kopírovaní
std::shared_ptr. Znižuje sa pri zničenístd::shared_ptr. Keď toto počítadlo dosiahne nulu, uvoľní sa riadený objekt. - Počítadlo slabých odkazov (weak count): Zvyšuje sa pri vytvorení
std::weak_ptrzstd::shared_ptr. Znižuje sa pri zničenístd::weak_ptr. Riadiaci blok sa uvoľní, keď obe počítadlá — silné a slabé — dosiahnu nulu.
Použitie std::make_shared je preferované pred priamym vytvorením s new, pretože môže alokovať objekt a riadiaci blok v jednom bloku pamäte, čo zlepšuje výkon a znižuje fragmentáciu.
Atomové počítadlá robia std::shared_ptr bezpečným pre použitie v viacvláknových scenároch, hoci prístup k riadenému objektu nie je predvolený synchronizovaný.
Príklad:
#include <iostream>
#include <memory>
struct MyObject {
int data;
MyObject(int d) : data(d) {
std::cout << "MyObject(" << data << ") created\n";
}
~MyObject() {
std::cout << "MyObject(" << data << ") destroyed\n";
}
};
int main() {
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
// silné počítadlo: 1, slabé počítadlo: 0
{
std::shared_ptr<MyObject> ptr2 = ptr1;
// silné počítadlo: 2, slabé počítadlo: 0
std::weak_ptr<MyObject> weak_ptr = ptr1;
// silné počítadlo: 2, slabé počítadlo: 1
if (auto locked_ptr = weak_ptr.lock()) {
// silné počítadlo: 3, slabé počítadlo: 1 (vo vnútri lock)
std::cout << "Object data: " << locked_ptr->data << std::endl;
}
// silné počítadlo: 2, slabé počítadlo: 1
} // ptr2 odchádza z rozsahu
// silné počítadlo: 1, slabé počítadlo: 1
// Objekt ešte nebol zničený, pretože silné počítadlo == 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// silné počítadlo: 1, slabé počítadlo: 2
} // weak_ptr2 odchádza z rozsahu
// silné počítadlo: 1, slabé počítadlo: 1
} // ptr1 odchádza z rozsahu
// silné počítadlo: 0, slabé počítadlo: 1
// Objekt je zničený, pretože silné počítadlo dosiahlo 0
// Riadiaci blok zostáva, kým sa slabé počítadlo nezníži na 0