Da trilha de C++ Este conceito ainda não saiu como card do dia. ir para o card de hoje

C++ Memória Intermediário

Smart pointers

Smart pointers são wrappers que gerenciam o tempo de vida de objetos alocados dinamicamente, liberando a memória automaticamente quando não são mais necessários. Eles evitam vazamentos de memória e são a forma moderna de expressar posse em C++.

O std::unique_ptr representa posse exclusiva: só um ponteiro pode ser dono do recurso. Ele não pode ser copiado, apenas movido. Já o std::shared_ptr permite posse compartilhada, mantendo um contador de referências que libera o objeto quando o último dono é destruído. O std::weak_ptr observa um shared_ptr sem aumentar o contador, útil para quebrar ciclos de referência.

A função std::make_unique (C++14) cria um unique_ptr de forma segura e concisa, evitando o uso explícito de new. Para shared_ptr, existe std::make_shared, que também é preferível por eficiência.

Neste card, você verá como usar cada um desses smart pointers e quando escolher cada tipo.

Pontos-chave

  • std::unique_ptr tem posse exclusiva e não pode ser copiado, apenas movido.
  • std::shared_ptr usa contagem de referências para liberar o objeto quando o último dono morre.
  • std::weak_ptr observa um shared_ptr sem incrementar o contador, evitando ciclos.
  • Prefira std::make_unique e std::make_shared em vez de new explícito.
  • Smart pointers liberam memória automaticamente ao sair de escopo.
smart_pointers.cpp
#include <iostream>
#include <memory>
#include <string>

struct Recurso {
    std::string nome;
    Recurso(std::string n) : nome(std::move(n)) {
        std::cout << "Criado: " << nome << '\n';
    }
    ~Recurso() {
        std::cout << "Destruido: " << nome << '\n';
    }
};

int main() {
    // unique_ptr: posse exclusiva
    auto u = std::make_unique<Recurso>("unique");
    std::cout << "Usando " << u->nome << '\n';

    // shared_ptr: posse compartilhada
    auto s1 = std::make_shared<Recurso>("shared");
    {
        auto s2 = s1; // copia, contador vai a 2
        std::cout << "shared use_count: " << s1.use_count() << '\n';
    } // s2 destruido, contador volta a 1
    std::cout << "shared use_count: " << s1.use_count() << '\n';

    // weak_ptr: observa sem possuir
    std::weak_ptr<Recurso> w = s1;
    if (auto locked = w.lock()) {
        std::cout << "weak lock: " << locked->nome << '\n';
    }

    return 0;
}

Exercícios

  1. 1
    Fácil

    Criando e usando unique_ptr

    Crie um std::unique_ptr para um int com valor 42 usando std::make_unique. Imprima o valor e depois libere o ponteiro com reset().

    Resolver
  2. 2
    Médio

    Compartilhamento com shared_ptr

    Crie um std::shared_ptr<std::string> com o valor "compartilhado". Faça uma cópia e imprima o use_count antes e depois de a cópia sair de escopo.

    Resolver
  3. 3
    Desafio

    Evitando ciclo com weak_ptr

    Modele uma relação pai-filho onde o pai tem um shared_ptr para o filho e o filho tem um weak_ptr para o pai. Crie as classes Pai e Filho, instancie e verifique que não há vazamento (o destrutor de ambos é chamado).

    Resolver

Continue estudando