Sobes.tech
Middle

Come funziona shared_ptr in C++?

sobes.tech AI

Risposta dell'AI

shared_ptr — è un puntatore intelligente che implementa la semantica di proprietà di una risorsa condivisa. Memorizza un puntatore all'oggetto e un puntatore al blocco di controllo.

Il blocco di controllo contiene:

  • Contatore di riferimenti forti (reference count).
  • Contatore di riferimenti deboli (weak count).
  • Functor di eliminazione personalizzato (deleter), se specificato.
  • Allocatore personalizzato, se specificato.
  • Puntatore all'oggetto memorizzato (lo stesso di quello memorizzato in shared_ptr).

Principio di funzionamento:

  1. Creazione: Quando si crea il primo shared_ptr che punta a un oggetto, viene creato il blocco di controllo e i contatori di riferimenti vengono inizializzati: forti — 1, deboli — 0.
    std::shared_ptr<int> ptr1 = std::make_shared<int>(10); // Crea un oggetto int e un blocco di controllo
    
  2. Copia: Quando si copia un shared_ptr, il contatore di riferimenti forti nel blocco di controllo aumenta di 1.
    std::shared_ptr<int> ptr2 = ptr1; // Aumenta il contatore di riferimenti forti
    
  3. Assegnazione: Quando si assegna un shared_ptr, la risorsa vecchia viene decrementata (il contatore di riferimenti forti diminuisce), e la nuova risorsa viene incrementata (aumenta).
    std::shared_ptr<int> ptr3;
    ptr3 = ptr1; // Decrementa la vecchia risorsa di ptr3, Incrementa la risorsa di ptr1
    
  4. Distruzione: Quando un shared_ptr viene distrutto (ad esempio, uscita dal scope), il contatore di riferimenti forti viene decrementato.
    {
        std::shared_ptr<int> ptr4 = ptr1; // Aumenta il contatore di riferimenti forti
        // ptr4 esce dal scope
    } // Decrementa il contatore di riferimenti forti
    
  5. Rilascio della risorsa: Quando il contatore di riferimenti forti raggiunge zero, la risorsa (l'oggetto puntato da shared_ptr) viene eliminata usando il functor di eliminazione definito (o delete di default).
  6. Rilascio del blocco di controllo: Il blocco di controllo viene liberato quando entrambi i contatori (forti e deboli) raggiungono zero.

Vantaggi:

  • Gestione automatica della memoria per risorse condivise.
  • Sicurezza contro doppie liberazioni.
  • Supporto per functor di eliminazione personalizzati.

Svantaggi:

  • Le referenze cicliche possono portare a perdite di memoria (risolto con weak_ptr).
  • Piccolo aumento dei costi a causa del blocco di controllo e delle operazioni atomiche sui contatori.
  • Sicurezza nelle operazioni con lo stesso shared_ptr (copia, assegnazione, modifica del puntatore memorizzato), ma non con l'oggetto a cui punta.