Senior
Como implementar um ponteiro inteligente para um ou vários objetos?
sobes.tech IA
Resposta da IA
Para um único objeto: unique_ptr ou shared_ptr.
Para múltiplos objetos: shared_ptr (propriedade compartilhada) ou weak_ptr (observação sem participação na gestão do ciclo de vida).
#include <memory>
#include <vector>
// Exemplo de classe de objeto
class MyObject {
public:
MyObject() { /* Construtor */ }
~MyObject() { /* Destruidor */ }
};
// Para um único objeto: unique_ptr (propriedade exclusiva)
void single_unique_ptr() {
std::unique_ptr<MyObject> ptr = std::make_unique<MyObject>();
// O objeto será eliminado automaticamente ao sair do escopo
}
// Para um único objeto: shared_ptr (propriedade compartilhada)
void single_shared_ptr() {
std::shared_ptr<MyObject> ptr = std::make_shared<MyObject>();
// A contagem de proprietários aumenta
std::shared_ptr<MyObject> another_ptr = ptr;
// O objeto será eliminado quando o último shared_ptr deixar de referenciá-lo
}
// Para múltiplos objetos: vetor com shared_ptr
void multiple_shared_ptr() {
std::vector<std::shared_ptr<MyObject>> objects;
objects.push_back(std::make_shared<MyObject>());
objects.push_back(std::make_shared<MyObject>());
// Cada objeto é gerido pelo seu próprio shared_ptr no vetor
// Os objetos serão eliminados após a eliminação dos shared_ptr correspondentes
}
// Para múltiplos objetos: vetor com unique_ptr
void multiple_unique_ptr() {
std::vector<std::unique_ptr<MyObject>> objects;
objects.push_back(std::make_unique<MyObject>());
objects.push_back(std::make_unique<MyObject>());
// Neste caso, o vetor possui os ponteiros únicos
// Os objetos serão eliminados ao sair do escopo do vetor
// Nota: unique_ptr não pode ser copiado, apenas movido (move)
std::unique_ptr<MyObject> moved_ptr = std::move(objects[0]);
}
Comparação entre unique_ptr e shared_ptr:
| Característica | std::unique_ptr |
std::shared_ptr |
|---|---|---|
| Propriedade | Única | Compartilhada (contador de referências) |
| Cópia | Não (apenas movimento) | Sim |
| Desempenho | Um pouco mais rápido (sem custos de contador de referências) | Um pouco mais lento (contador de referências) |
| Referências cíclicas | Não protege | Pode causar vazamentos de memória (requer weak_ptr) |
std::weak_ptr é usado para observar um objeto gerenciado por shared_ptr sem aumentar o contador de referências, evitando problemas de referências cíclicas.
#include <memory>
class Node {
public:
std::shared_ptr<Node> next;
std::weak_ptr<Node> previous; // Uso de weak_ptr para evitar referência cíclica
Node() = default;
~Node() { /* Destructeur */ }
};
void weak_ptr_example() {
std::shared_ptr<Node> node1 = std::make_shared<Node>();
std::shared_ptr<Node> node2 = std::make_shared<Node>();
node1->next = node2;
node2->previous = node1; // Usamos weak_ptr
// Pode obter um shared_ptr de weak_ptr para acessar o objeto
if (std::shared_ptr<Node> locked_node = node2->previous.lock()) {
// Se o objeto ainda estiver vivo
// ... trabalhar com locked_node
} else {
// O objeto já foi eliminado
}
}