Menu
Coddy logo textTech

Smart Pointers em C++

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 15 de 104.

Smart pointers são classes wrapper que gerenciam automaticamente a memória heap para você. Eles eliminam a necessidade de chamadas delete manuais ao limpar a memória quando o ponteiro sai de escopo.

Inclua o cabeçalho <memory> para usar ponteiros inteligentes.

unique_ptr - propriedade exclusiva. Apenas um ponteiro pode possuir o recurso por vez.

#include <memory>

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // Use como um ponteiro comum

// Não pode copiar, mas pode transferir a posse
std::unique_ptr<Player> player2 = std::move(player);
// player agora é nullptr

shared_ptr - propriedade compartilhada. Múltiplos ponteiros podem possuir o mesmo recurso. A memória é liberada quando o último proprietário é destruído.

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // Ambos possuem o recurso

std::cout << p1.use_count();  // Imprime 2

weak_ptr - observador que não detém a posse de um shared_ptr. Útil para quebrar referências circulares.

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // Converter para shared_ptr
    locked->attack();
}

Use unique_ptr por padrão para propriedade única. Use shared_ptr quando múltiplos objetos precisarem compartilhar um recurso. Use weak_ptr para observar sem estender o tempo de vida.

Prefira make_unique e make_shared em vez do new bruto.

challenge icon

Desafio

Fácil

Vamos construir um sistema de compartilhamento de documentos que demonstra os diferentes modelos de propriedade de smart pointers. Você verá como o unique_ptr impõe a propriedade exclusiva, como o shared_ptr permite múltiplos proprietários e como o weak_ptr pode observar sem afetar o tempo de vida.

Você criará dois arquivos para organizar seu código:

  • Document.h: Defina uma classe Document que representa um documento compartilhável. Ela deve ter:
    • Um atributo privado title (string)
    • Um construtor que recebe um título e imprime "Document created: <title>"
    • Um destruidor que imprime "Document deleted: <title>"
    • Um método getTitle() que retorna o título
  • main.cpp: Demonstre todos os três tipos de smart pointers lendo um título de documento da entrada e, em seguida:
    • Crie um unique_ptr para um Document com o título de entrada
    • Imprima "Unique owner: <title>"
    • Transfira a propriedade para outro unique_ptr usando std::move
    • Imprima "Ownership transferred"
    • Crie um shared_ptr para um novo Document com o título "SharedDoc"
    • Crie um segundo shared_ptr apontando para o mesmo documento
    • Imprima "Shared owners: <count>" usando use_count()
    • Crie um weak_ptr a partir de um dos shared pointers
    • Use lock() para acessar o documento através do weak pointer e imprima "Weak access: <title>"

Lembre-se de incluir <memory> para os smart pointers. Use std::make_unique e std::make_shared para criar seus smart pointers. As mensagens do destruidor ajudarão você a ver quando cada documento é limpo automaticamente ao final do programa.

Inclua seu arquivo de cabeçalho no main.cpp usando #include "Document.h".

Folha de consulta

Smart pointers (ponteiros inteligentes) são classes wrapper que gerenciam automaticamente a memória heap. Inclua o cabeçalho <memory> para utilizá-los.

unique_ptr

Propriedade exclusiva - apenas um ponteiro pode possuir o recurso por vez:

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // Use como um ponteiro comum

// Transfer ownership with std::move
std::unique_ptr<Player> player2 = std::move(player);
// player is now nullptr

shared_ptr

Propriedade compartilhada - múltiplos ponteiros podem possuir o mesmo recurso. A memória é liberada quando o último proprietário é destruído:

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // Both own the resource

std::cout << p1.use_count();  // Prints 2

weak_ptr

Observador sem propriedade de um shared_ptr. Útil para quebrar referências circulares:

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // Convert to shared_ptr
    locked->attack();
}

Melhores práticas: Use unique_ptr por padrão para propriedade única. Use shared_ptr quando múltiplos objetos precisarem compartilhar um recurso. Use weak_ptr para observar sem estender o tempo de vida. Prefira make_unique e make_shared em vez do new bruto.

Experimente você mesmo

#include <iostream>
#include <memory>
#include <string>
#include "Document.h"

using namespace std;

int main() {
    string inputTitle;
    cin >> inputTitle;

    // TODO: Criar um unique_ptr para um Document com inputTitle
    // usando std::make_unique

    // TODO: Imprimir "Unique owner: <title>"

    // TODO: Transferir a posse para outro unique_ptr usando std::move

    // TODO: Imprimir "Ownership transferred"

    // TODO: Criar um shared_ptr para um novo Document com o título "SharedDoc"
    // usando std::make_shared

    // TODO: Criar um segundo shared_ptr apontando para o mesmo documento

    // TODO: Imprimir "Shared owners: <count>" usando use_count()

    // TODO: Criar um weak_ptr a partir de um dos shared pointers

    // TODO: Usar lock() para acessar o documento através do weak_ptr
    // e imprimir "Weak access: <title>"

    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos