Middle
Kokiu pagrindu keli shared_ptr objektai gali nurodyti tą patį rodyklį?
sobes.tech AI
Atsakymas iš AI
Keli std::shared_ptr objektai gali nurodyti į tą patį rodyklę dėl valdymo bloko (control block) buvimo.
Valdymo blokas, susijęs su valdomu objektu, turi:
- Stiprių nuorodų skaitiklis (strong reference count): Didėja, kai kuriamas naujas
shared_ptrtam pačiam objektui. Mažėja, kaishared_ptrsunaikinamas. Kai pasiekia nulį, susietas objektas (rodyklė) yra ištrinamas. - Silpnų nuorodų skaitiklis (weak reference count): Naudojamas
std::weak_ptr. Didėja, kaiweak_ptrsukuriamas išshared_ptr. Mažėja, kaiweak_ptrsunaikinamas. Kai abu skaitikliai pasiekia nulį, valdymo blokas yra ištrinamas. - Savyje esantis rodyklė į valdomą objektą: Ne duomenų rodyklė, o ta, kuri valdomo bloko.
Kai sukuriate shared_ptr iš esamo shared_ptr (kopijavimas, priskyrimas kopijavimu), jie pradeda naudoti tą patį valdymo bloką, ir stiprių nuorodų skaitiklis šiame bloke didėja.
Pavyzdys:
#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() {
// Pirmas `shared_ptr` sukūrimas:
// Sukuriamas valdymo blokas ir MyData objektas:
// stiprių skaitiklis: 1, silpnų: 0.
std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
// Antras `shared_ptr` sukūrimas iš ptr1:
// Naudojamas tas pats valdymo blokas:
// stiprių skaitiklis padidėja iki 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";
// Trečias `shared_ptr` sukūrimas iš ptr1:
// Naudojamas tas pats valdymo blokas:
// stiprių skaitiklis padidėja iki 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 << "Išeiti iš apimties.\n";
// ptr3 išeina iš apimties:
// stiprių skaitiklis sumažėja iki 2.
// ptr2 išeina iš apimties:
// stiprių skaitiklis sumažėja iki 1.
// ptr1 išeina iš apimties:
// stiprių skaitiklis sumažėja iki 0.
// MyData objektas sunaikinamas.
// Valdymo blokas ištrinamas.
}
Kiekvienas shared_ptr objektas turi savo nuorodą į valdymo bloką ir savo nuorodą į duomenų objektą. Kopijuojant shared_ptr, kopijuojami abu šie rodyklės, ir stiprių nuorodų skaitiklis bendrame bloke didėja. Taip visi shared_ptr nurodo į tą patį valdymo bloką, kuris stebi jų kopijų skaičių ir nustato valdomo išteklių išlaisvinimo momentą.