Su quale base più oggetti shared_ptr possono fare riferimento allo stesso puntatore?
sobes.tech AI
Risposta dell'AI
Più oggetti std::shared_ptr possono fare riferimento allo stesso puntatore grazie alla presenza di un blocco di controllo (control block).
Il blocco di controllo associato all'oggetto gestito contiene:
- Contatore di riferimenti forti (strong reference count): Aumenta quando si crea un nuovo
shared_ptrper lo stesso oggetto. Diminuisce quando si distrugge unshared_ptr. Quando raggiunge zero, l'oggetto (puntatore) associato viene eliminato. - Contatore di riferimenti deboli (weak reference count): Usato per
std::weak_ptr. Aumenta quando si crea unweak_ptrda unshared_ptr. Diminuisce quando si distrugge unweak_ptr. Quando entrambi i contatori sono zero, il blocco di controllo viene eliminato. - Puntatore proprio all'oggetto gestito: Non il puntatore ai dati stesso, ma quello gestito dal blocco.
Quando si crea un shared_ptr da un altro esistente (copia, assegnazione-copia), entrambi iniziano a usare lo stesso blocco di controllo, e il contatore di riferimenti forti in questo blocco aumenta.
Esempio:
#include <memory>
#include <iostream>
struct MyData {
int value;
MyData(int v) : value(v) { std::cout << "MyData(" << value << ") creato.\n"; }
~MyData() { std::cout << "MyData(" << value << ") distrutto.\n"; }
};
int main() {
// Creazione del primo shared_ptr.
// Creazione del blocco di controllo e dell'oggetto MyData.
// Contatori: forte: 1, debole: 0.
std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
std::cout << "conteggio di utilizzo di ptr1: " << ptr1.use_count() << "\n";
// Creazione di un secondo shared_ptr da ptr1.
// Usa lo stesso blocco di controllo.
// Il contatore forte aumenta a 2.
std::shared_ptr<MyData> ptr2 = ptr1;
std::cout << "conteggio di utilizzo di ptr1: " << ptr1.use_count() << "\n";
std::cout << "conteggio di utilizzo di ptr2: " << ptr2.use_count() << "\n";
// Creazione di un terzo shared_ptr da ptr1.
// Usa lo stesso blocco di controllo.
// Il contatore forte aumenta a 3.
std::shared_ptr<MyData> ptr3 = ptr1;
std::cout << "conteggio di utilizzo di ptr1: " << ptr1.use_count() << "\n";
std::cout << "conteggio di utilizzo di ptr2: " << ptr2.use_count() << "\n";
std::cout << "conteggio di utilizzo di ptr3: " << ptr3.use_count() << "\n";
std::cout << "Uscita dallo scope.\n";
// ptr3 esce dallo scope.
// Il contatore forte diminuisce a 2.
// ptr2 esce dallo scope.
// Il contatore forte diminuisce a 1.
// ptr1 esce dallo scope.
// Il contatore forte diminuisce a 0.
// L'oggetto MyData viene distrutto.
// Il blocco di controllo viene eliminato.
}
Ogni oggetto shared_ptr contiene il proprio puntatore al blocco di controllo e il proprio puntatore all'oggetto dati. Quando si copia un shared_ptr, entrambi i puntatori vengono copiati, e il contatore di riferimenti forti nel blocco comune aumenta. In questo modo, tutti i shared_ptr puntano allo stesso blocco di controllo, che tiene traccia del numero di copie che possiedono la risorsa e determina il momento di distruzione della risorsa gestita.