Sobes.tech
Middle

Auf welcher Grundlage können mehrere Objekte shared_ptr auf denselben Zeiger verweisen?

sobes.tech KI

Antwort von AI

Mehrere Objekte std::shared_ptr können auf denselben Zeiger verweisen, dank eines Steuerblocks (control block).

Der Steuerblock, der mit dem verwalteten Objekt verbunden ist, enthält:

  • Starker Referenzzähler (strong reference count): Er erhöht sich beim Erstellen eines neuen shared_ptr für dasselbe Objekt. Er verringert sich beim Zerstören eines shared_ptr. Wenn er null erreicht, wird das zugehörige Objekt (Zeiger) gelöscht.
  • Schwacher Referenzzähler (weak reference count): Wird für std::weak_ptr verwendet. Er erhöht sich beim Erstellen eines weak_ptr aus einem shared_ptr. Er verringert sich beim Zerstören eines weak_ptr. Wenn beide Zähler null sind, wird der Steuerblock gelöscht.
  • Eigener Zeiger auf das verwaltete Objekt: Nicht der Datenzeiger selbst, sondern der, der vom Steuerblock verwaltet wird.

Wenn Sie einen shared_ptr aus einem bestehenden shared_ptr erstellen (Kopie, Zuweisung-Kopie), verwenden beide denselben Steuerblock, und der starke Referenzzähler in diesem Block erhöht sich.

Beispiel:

#include <memory>
#include <iostream>

struct MyData {
    int value;
    MyData(int v) : value(v) { std::cout << "MyData(" << value << ") erstellt.\n"; }
    ~MyData() { std::cout << "MyData(" << value << ") zerstört.\n"; }
};

int main() {
    // Erstes shared_ptr wird erstellt.
    // Steuerblock und MyData-Objekt werden erstellt.
    // Zähler: strong: 1, weak: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "Verwendungszähler von ptr1: " << ptr1.use_count() << "\n";

    // Zweites shared_ptr wird aus ptr1 erstellt.
    // Verwendet denselben Steuerblock.
    // Der starke Zähler erhöht sich auf 2.
    std::shared_ptr<MyData> ptr2 = ptr1;
    std::cout << "Verwendungszähler von ptr1: " << ptr1.use_count() << "\n";
    std::cout << "Verwendungszähler von ptr2: " << ptr2.use_count() << "\n";

    // Drittes shared_ptr wird aus ptr1 erstellt.
    // Verwendet denselben Steuerblock.
    // Der starke Zähler erhöht sich auf 3.
    std::shared_ptr<MyData> ptr3 = ptr1;
     std::cout << "Verwendungszähler von ptr1: " << ptr1.use_count() << "\n";
    std::cout << "Verwendungszähler von ptr2: " << ptr2.use_count() << "\n";
    std::cout << "Verwendungszähler von ptr3: " << ptr3.use_count() << "\n";

    std::cout << "Verlassen des Gültigkeitsbereichs.\n";
    // ptr3 verlässt den Gültigkeitsbereich.
    // Der starke Zähler sinkt auf 2.
    // ptr2 verlässt den Gültigkeitsbereich.
    // Der starke Zähler sinkt auf 1.
    // ptr1 verlässt den Gültigkeitsbereich.
    // Der starke Zähler sinkt auf 0.
    // Das MyData-Objekt wird zerstört.
    // Der Steuerblock wird zerstört.
}

Jedes shared_ptr-Objekt enthält einen eigenen Zeiger auf den Steuerblock und einen eigenen Zeiger auf das Datenobjekt. Beim Kopieren eines shared_ptr werden beide Zeiger kopiert, und der starke Referenzzähler im gemeinsamen Steuerblock wird erhöht. Somit zeigen alle shared_ptr auf denselben Steuerblock, der die Anzahl der Besitzenden verfolgt und den Zeitpunkt der Zerstörung der verwalteten Ressource bestimmt.