Sobes.tech
Middle

Pe ce bază pot mai multe obiecte shared_ptr face referire la același pointer?

sobes.tech AI

Răspuns de la AI

Mai multe obiecte std::shared_ptr pot referi la aceeași pointer datorită existenței unui bloc de control (control block).

Blocul de control asociat cu obiectul gestionat conține:

  • Contorul de referințe puternice (strong reference count): Crește la crearea unui nou shared_ptr pentru același obiect. Scade la distrugerea unui shared_ptr. Când ajunge la zero, obiectul asociat (pointerul) este șters.
  • Contorul de referințe slabe (weak reference count): Folosit pentru std::weak_ptr. Crește la crearea unui weak_ptr dintr-un shared_ptr. Scade la distrugerea unui weak_ptr. Când ambii contori ajung la zero, blocul de control este șters.
  • Pointerul propriu către obiectul gestionat: Nu pointerul de date în sine, ci cel gestionat de bloc.

Când creezi un shared_ptr dintr-un alt shared_ptr existent (copiere, atribuție-copiere), amândoi încep să folosească același bloc de control, iar contorul de referințe puternice din acest bloc crește.

Exemplu:

#include <memory>
#include <iostream>

struct MyData {
    int value;
    MyData(int v) : value(v) { std::cout << "MyData(" << value << ") creat.\n"; }
    ~MyData() { std::cout << "MyData(" << value << ") distrus.\n"; }
};

int main() {
    // Se creează primul shared_ptr.
    // Se creează blocul de control și obiectul MyData.
    // Contorii: puternic: 1, slab: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "numărul de utilizare ptr1: " << ptr1.use_count() << "\n";

    // Se creează al doilea shared_ptr din ptr1.
    // Se folosește același bloc de control.
    // Contorul puternic crește la 2.
    std::shared_ptr<MyData> ptr2 = ptr1;
    std::cout << "numărul de utilizare ptr1: " << ptr1.use_count() << "\n";
    std::cout << "numărul de utilizare ptr2: " << ptr2.use_count() << "\n";

    // Se creează al treilea shared_ptr din ptr1.
    // Se folosește același bloc de control.
    // Contorul puternic crește la 3.
    std::shared_ptr<MyData> ptr3 = ptr1;
     std::cout << "numărul de utilizare ptr1: " << ptr1.use_count() << "\n";
    std::cout << "numărul de utilizare ptr2: " << ptr2.use_count() << "\n";
    std::cout << "numărul de utilizare ptr3: " << ptr3.use_count() << "\n";

    std::cout << "Ieșire din scop.\n";
    // ptr3 iese din scop.
    // Contorul puternic scade la 2.
    // ptr2 iese din scop.
    // Contorul puternic scade la 1.
    // ptr1 iese din scop.
    // Contorul puternic scade la 0.
    // Obiectul MyData este distrus.
    // Blocul de control este șters.
}

Fiecare obiect shared_ptr conține propriul pointer către blocul de control și propriul pointer către obiectul de date. La copierea unui shared_ptr, se copiază ambii pointeri, iar contorul de referințe puternice din blocul comun crește. Astfel, toate shared_ptr indică către același bloc de control, care urmărește numărul de copii deținători și determină momentul distrugerii resursei gestionate.