Middle
Jak funguje čítač odkazů v std::shared_ptr?
sobes.tech AI
Odpověď od AI
Počítadlo odkazů ve std::shared_ptr je uloženo v samostatném objektu — v řídícím bloku (control block).
Tento řídící blok je vytvořen:
- Při prvním vytvoření
std::shared_ptrz ukazatele. - Při vytvoření
std::shared_ptrs vlastním deleterem nebo alokátorem. - Při použití
std::make_sharednebostd::allocate_shared.
Tento řídící blok obsahuje minimálně dva počítadla:
- Počítadlo silných odkazů (strong count): Zvyšuje se při vytváření nebo kopírování
std::shared_ptr. Snižuje se při ničenístd::shared_ptr. Když toto počítadlo dosáhne nuly, je spravovaný objekt uvolněn. - Počítadlo slabých odkazů (weak count): Zvyšuje se při vytvoření
std::weak_ptrzstd::shared_ptr. Snižuje se při ničenístd::weak_ptr. Řídící blok je uvolněn, když obě počítadla — silné i slabé — dosáhnou nuly.
Použití std::make_shared je preferováno před přímým vytvářením pomocí new, protože může alokovat objekt i řídící blok v jednom bloku paměti, což zlepšuje výkon a snižuje fragmentaci.
Počítadla jsou atomická, což činí std::shared_ptr bezpečným pro použití ve vícevláknových scénářích, ačkoliv přístup ke spravovanému objektu není ve výchozím nastavení synchronizován.
Příklad:
#include <iostream>
#include <memory>
struct MyObject {
int data;
MyObject(int d) : data(d) {
std::cout << "MyObject(" << data << ") vytvořen\n";
}
~MyObject() {
std::cout << "MyObject(" << data << ") zničen\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 (dočasně v lock)
std::cout << "Data objektu: " << locked_ptr->data << std::endl;
}
// silné počítadlo: 2, slabé počítadlo: 1
} // ptr2 končí v scope
// silné počítadlo: 1, slabé počítadlo: 1
// Objekt ještě nebyl zničen, protože silné počítadlo == 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// silné počítadlo: 1, slabé počítadlo: 2
} // weak_ptr2 končí v scope
// silné počítadlo: 1, slabé počítadlo: 1
} // ptr1 končí v scope
// silné počítadlo: 0, slabé počítadlo: 1
// Objekt je zničen, protože silné počítadlo dosáhlo nuly
// Řídící blok zůstává, dokud slabé počítadlo nedosáhne nuly