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_ptrfür dasselbe Objekt. Er verringert sich beim Zerstören einesshared_ptr. Wenn er null erreicht, wird das zugehörige Objekt (Zeiger) gelöscht. - Schwacher Referenzzähler (weak reference count): Wird für
std::weak_ptrverwendet. Er erhöht sich beim Erstellen einesweak_ptraus einemshared_ptr. Er verringert sich beim Zerstören einesweak_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.