Middle
O que você sabe sobre ponteiros inteligentes em C++?
sobes.tech IA
Resposta da IA
Os ponteiros inteligentes são wrappers RAII sobre ponteiros normais (crus) em C++, que fornecem controlo automático do tempo de vida da memória alocada, prevenindo fugas.
Os principais tipos de ponteiros inteligentes na biblioteca padrão de C++:
std::unique_ptrstd::shared_ptrstd::weak_ptr
std::unique_ptr
- Possui o recurso de forma exclusiva.
- Não pode ser copiado, mas pode ser movido.
- Usado para a posse única do recurso.
- Os custos adicionais são mínimos, equivalentes a um ponteiro cru.
// exemplo de unique_ptr
#include <memory>
#include <iostream>
int main() {
std::unique_ptr<int> ptr = std::make_unique<int>(10);
std::cout << *ptr << std::endl; // 10
// std::unique_ptr<int> ptr2 = ptr; // Erro de compilação: unique_ptr não é copiado
std::unique_ptr<int> ptr3 = std::move(ptr); // Movimento de posse
std::cout << *ptr3 << std::endl; // 10
// std::cout << *ptr << std::endl; // Comportamento indefinido: ptr agora está vazio
return 0;
}
std::shared_ptr
- Permite que múltiplos ponteiros partilhem a posse de um recurso.
- Usa um contador de referências. A memória é libertada quando o contador chega a zero.
- Pode ser copiado. Cada cópia aumenta o contador de referências.
- Tem custos adicionais mais altos em comparação com
unique_ptrdevido à gestão do contador.
// exemplo de shared_ptr
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 1)
std::shared_ptr<int> ptr2 = ptr1; // Cópia, aumenta use_count
std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
std::shared_ptr<int> ptr3 = ptr1; // Outra cópia
std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
return 0;
}
std::weak_ptr
- Não possui o recurso e não aumenta o contador de referências.
- Usado para resolver o problema de referências cíclicas entre
shared_ptr. - Permite aceder ao recurso apontado por
shared_ptr, mas não impede a sua eliminação. - Para aceder ao recurso, é necessário converter
weak_ptremshared_ptrusando o métodolock().
// exemplo de weak_ptr
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<int> shared_ptr_int = std::make_shared<int>(30);
std::weak_ptr<int> weak_ptr_int = shared_ptr_int;
if (auto locked_ptr = weak_ptr_int.lock()) {
std::cout << *locked_ptr << std::endl; // 30
} else {
std::cout << "Recurso foi libertado." << std::endl;
}
shared_ptr_int.reset(); // Recurso libertado
if (auto locked_ptr = weak_ptr_int.lock()) {
std::cout << *locked_ptr << std::endl;
} else {
std::cout << "Recurso foi libertado." << std::endl; // Recurso foi libertado.
}
return 0;
}
O uso de ponteiros inteligentes é uma boa prática na programação moderna em C++, pois reduz significativamente a probabilidade de erros na gestão de memória.