Sobes.tech
Middle

Como funciona o shared_ptr em C++?

sobes.tech IA

Resposta da IA

shared_ptr — é um ponteiro inteligente que implementa a semântica de propriedade de um recurso compartilhado. Ele armazena um ponteiro para o objeto e um ponteiro para o bloco de controlo.

O bloco de controlo contém:

  • Contador de referências fortes (reference count).
  • Contador de referências fracas (weak count).
  • Functor de eliminação personalizado (deleter), se especificado.
  • Alocador personalizado, se especificado.
  • Ponteiro para o objeto armazenado (o mesmo que é armazenado no shared_ptr).

Princípio de funcionamento:

  1. Criação: Ao criar o primeiro shared_ptr que aponta para um objeto, o bloco de controlo é criado, e os contadores de referências são inicializados: fortes — 1, fracos — 0.
    std::shared_ptr<int> ptr1 = std::make_shared<int>(10); // Cria um objeto int e um bloco de controlo
    
  2. Cópia: Ao copiar um shared_ptr, o contador de referências fortes no bloco de controlo aumenta em 1.
    std::shared_ptr<int> ptr2 = ptr1; // Aumenta o contador de referências fortes
    
  3. Atribuição: Ao atribuir um shared_ptr, o recurso antigo é decrementado (o contador de referências fortes diminui), e o novo recurso é incrementado (aumenta).
    std::shared_ptr<int> ptr3;
    ptr3 = ptr1; // Decrementa o recurso antigo de ptr3, Incrementa o recurso de ptr1
    
  4. Eliminação: Ao destruir um shared_ptr (por exemplo, sair do âmbito), o contador de referências fortes é decrementado.
    {
        std::shared_ptr<int> ptr4 = ptr1; // Aumenta o contador de referências fortes
        // ptr4 sai do âmbito
    } // Decrementa o contador de referências fortes
    
  5. Liberação do recurso: Quando o contador de referências fortes chega a zero, o recurso (o objeto apontado por shared_ptr) é eliminado usando o functor de eliminação definido (ou delete por padrão).
  6. Liberação do bloco de controlo: O bloco de controlo é liberado quando ambos os contadores (fortes e fracos) atingem zero.

Vantagens:

  • Gestão automática de memória para recursos partilhados.
  • Segurança contra libertações duplas.
  • Suporte para functors de eliminação personalizados.

Desvantagens:

  • Os enlaces cíclicos podem levar a fugas de memória (resolvido com weak_ptr).
  • Pequeno aumento nos custos devido ao bloco de controlo e operações atómicas nos contadores.
  • Segurança nas operações com o próprio shared_ptr (cópia, atribuição, alteração do ponteiro armazenado), mas não com o objeto ao qual aponta.