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_ptrtem posse exclusiva e não pode ser copiado, apenas movido.std::shared_ptrusa contagem de referências para liberar o objeto quando o último dono morre.std::weak_ptrobserva umshared_ptrsem incrementar o contador, evitando ciclos.- Prefira
std::make_uniqueestd::make_sharedem vez denewexplícito. - Smart pointers liberam memória automaticamente ao sair de escopo.
#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;
}