Sobes.tech
Middle

Op welke basis kunnen meerdere shared_ptr-objecten naar dezelfde pointer verwijzen?

sobes.tech AI

Antwoord van AI

Meerdere objecten std::shared_ptr kunnen naar dezelfde pointer verwijzen dankzij de aanwezigheid van een controleblok (control block).

Het controleblok dat gekoppeld is aan het beheerde object bevat:

  • Sterke referentieteller (strong reference count): Verhoogt bij het maken van een nieuwe shared_ptr voor hetzelfde object. Verlaagt bij het vernietigen van een shared_ptr. Wanneer deze nul wordt, wordt het bijbehorende object (pointer) verwijderd.
  • Zwakke referentieteller (weak reference count): Gebruikt voor std::weak_ptr. Verhoogt bij het maken van een weak_ptr uit een shared_ptr. Verlaagt bij het vernietigen van een weak_ptr. Wanneer beide tellers nul worden, wordt het controleblok verwijderd.
  • Eigen pointer naar het beheerde object: Niet de data pointer zelf, maar degene die door het controleblok wordt beheerd.

Wanneer je een shared_ptr maakt uit een bestaande shared_ptr (kopiëren, toewijzing-kopiëren), beginnen ze hetzelfde controleblok te gebruiken, en wordt de sterke referentieteller in dat blok verhoogd.

Voorbeeld:

#include <memory>
#include <iostream>

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

int main() {
    // Eerste shared_ptr wordt gemaakt.
    // Controleblok en MyData-object worden gemaakt.
    // Tellers: sterk: 1, zwak: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "gebruik tellen van ptr1: " << ptr1.use_count() << "\n";

    // Tweede shared_ptr wordt uit ptr1 gemaakt.
    // Gebruikt hetzelfde controleblok.
    // De sterke teller wordt verhoogd naar 2.
    std::shared_ptr<MyData> ptr2 = ptr1;
    std::cout << "gebruik tellen van ptr1: " << ptr1.use_count() << "\n";
    std::cout << "gebruik tellen van ptr2: " << ptr2.use_count() << "\n";

    // Derde shared_ptr wordt uit ptr1 gemaakt.
    // Gebruikt hetzelfde controleblok.
    // De sterke teller wordt verhoogd naar 3.
    std::shared_ptr<MyData> ptr3 = ptr1;
     std::cout << "gebruik tellen van ptr1: " << ptr1.use_count() << "\n";
    std::cout << "gebruik tellen van ptr2: " << ptr2.use_count() << "\n";
    std::cout << "gebruik tellen van ptr3: " << ptr3.use_count() << "\n";

    std::cout << "Scope verlaten.\n";
    // ptr3 verlaat scope.
    // De sterke teller daalt naar 2.
    // ptr2 verlaat scope.
    // De sterke teller daalt naar 1.
    // ptr1 verlaat scope.
    // De sterke teller daalt naar 0.
    // Het MyData-object wordt verwijderd.
    // Het controleblok wordt verwijderd.
}

Elk shared_ptr object bevat zijn eigen pointer naar het controleblok en zijn eigen pointer naar het gegevensobject. Bij kopiëren van een shared_ptr worden beide pointers gekopieerd, en wordt de sterke referentieteller in het gemeenschappelijke controleblok verhoogd. Op deze manier wijzen alle shared_ptr naar hetzelfde controleblok, dat het aantal bezittingen bijhoudt en het moment van vernietiging van de beheerde hulpbron bepaalt.