Middle
Kā darbojas atsauces skaitītājs std::shared_ptr?
sobes.tech AI
Atbilde no AI
std::shared_ptr saites skaitītājs tiek glabāts atsevišķā objektā — kontroles blokā (control block).
Šis kontroles bloks tiek izveidots:
- Pirmo reizi, kad
std::shared_ptrtiek izveidots no norādītāja. - Izveidojot
std::shared_ptrar lietotāja definētu dzēšēju vai alokatoru. - Izmantojot
std::make_sharedvaistd::allocate_shared.
Šis kontroles bloks satur vismaz divus skaitītājus:
- Stipro saišu skaitītājs (strong count): Palielinās, veidojot vai kopējot
std::shared_ptr. Samazinās, to iznīcinot. Kad šis skaitītājs sasniedz nulli, pārvaldītais objekts tiek atbrīvots. - Vāju saišu skaitītājs (weak count): Palielinās, veidojot
std::weak_ptrnostd::shared_ptr. Samazinās, to iznīcinot. Kontroles bloks tiek atbrīvots, kad abi skaitītāji — stiprais un vājš — sasniedz nulli.
std::make_shared ir vēlams izmantot, nevis tieši new lietot, jo tas var alocēt objektu un kontroles bloku vienā atmiņas blokā, uzlabojot veiktspēju un samazinot fragmentāciju.
Akmati skaitītāji nodrošina std::shared_ptr drošību daudzprocesu scenārijos, lai gan piekļuve pārvaldītajam objektam pēc noklusējuma nav sinhronizēta.
Piemērs:
#include <iostream>
#include <memory>
struct MyObject {
int data;
MyObject(int d) : data(d) {
std::cout << "MyObject(" << data << ") izveidots\n";
}
~MyObject() {
std::cout << "MyObject(" << data << ") iznīcināts\n";
}
};
int main() {
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
// stiprais skaitītājs: 1, vājš skaitītājs: 0
{
std::shared_ptr<MyObject> ptr2 = ptr1;
// stiprais skaitītājs: 2, vājš skaitītājs: 0
std::weak_ptr<MyObject> weak_ptr = ptr1;
// stiprais skaitītājs: 2, vājš skaitītājs: 1
if (auto locked_ptr = weak_ptr.lock()) {
// stiprais skaitītājs: 3, vājš skaitītājs: 1 (lock laikā)
std::cout << "Objekta dati: " << locked_ptr->data << std::endl;
}
// stiprais skaitītājs: 2, vājš skaitītājs: 1
} // ptr2 iziet no apjoma
// stiprais skaitītājs: 1, vājš skaitītājs: 1
// Objekts vēl nav iznīcināts, jo stiprais skaitītājs == 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// stiprais skaitītājs: 1, vājš skaitītājs: 2
} // weak_ptr2 iziet no apjoma
// stiprais skaitītājs: 1, vājš skaitītājs: 1
} // ptr1 iziet no apjoma
// stiprais skaitītājs: 0, vājš skaitītājs: 1
// Objekts tiek iznīcināts, jo stiprais skaitītājs kļuva par 0
// Kontroles bloks paliek līdz brīdim, kad vājš skaitītājs kļūst par 0