Middle
Kako radi brojač referenci u std::shared_ptr?
sobes.tech АИ
Одговор од АИ
Brojač veza u std::shared_ptr čuva se u posebnom objektu — kontrolnom bloku.
Kontrolni blok se kreira:
- Pri prvom kreiranju
std::shared_ptriz pokazivača. - Pri kreiranju
std::shared_ptrsa korisničkim brisačem ili alokatorom. - Pri korišćenju
std::make_sharedilistd::allocate_shared.
Ovaj kontrolni blok sadrži najmanje dva brojača:
- Brojač jakih veza (strong count): Povećava se pri kreiranju ili kopiranju
std::shared_ptr. Smanjuje se pri uništavanjustd::shared_ptr. Kada ovaj brojač postane nula, oslobađa se upravljani objekat. - Brojač slabih veza (weak count): Povećava se pri kreiranju
std::weak_ptrizstd::shared_ptr. Smanjuje se pri uništavanjustd::weak_ptr. Kontrolni blok se oslobađa kada oba brojača — jaki i slabi — postanu nula.
Korišćenje std::make_shared je poželjnije od direktnog kreiranja sa new, jer može alocirati objekat i kontrolni blok u istu memorijsku oblast, što poboljšava performanse i smanjuje fragmentaciju.
Aтомски brojači čine std::shared_ptr sigurnim za korišćenje u višepotresnim scenarijima, iako pristup upravljanom objektu po defaultu nije sinhronizovan.
Primer:
#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);
// jak brojač: 1, slabi brojač: 0
{
std::shared_ptr<MyObject> ptr2 = ptr1;
// jak brojač: 2, slabi brojač: 0
std::weak_ptr<MyObject> weak_ptr = ptr1;
// jak brojač: 2, slabi brojač: 1
if (auto locked_ptr = weak_ptr.lock()) {
// jak brojač: 3, slabi brojač: 1 (unutar lock)
std::cout << "Object data: " << locked_ptr->data << std::endl;
}
// jak brojač: 2, slabi brojač: 1
} // ptr2 izlazi iz opsega
// jak brojač: 1, slabi brojač: 1
// Objekat još uvek nije uništen, jer je jak brojač == 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// jak brojač: 1, slabi brojač: 2
} // weak_ptr2 izlazi iz opsega
// jak brojač: 1, slabi brojač: 1
} // ptr1 izlazi iz opsega
// jak brojač: 0, slabi brojač: 1
// Objekat se uništava, jer je jak brojač postao 0
// Kontrolni blok ostaje dok se slabi brojač ne smanji na 0