Sobes.tech
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_ptr iz pokazivača.
  • Pri kreiranju std::shared_ptr sa korisničkim brisačem ili alokatorom.
  • Pri korišćenju std::make_shared ili std::allocate_shared.

Ovaj kontrolni blok sadrži najmanje dva brojača:

  1. Brojač jakih veza (strong count): Povećava se pri kreiranju ili kopiranju std::shared_ptr. Smanjuje se pri uništavanju std::shared_ptr. Kada ovaj brojač postane nula, oslobađa se upravljani objekat.
  2. Brojač slabih veza (weak count): Povećava se pri kreiranju std::weak_ptr iz std::shared_ptr. Smanjuje se pri uništavanju std::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