Com base no que vários objetos shared_ptr podem referenciar o mesmo ponteiro?
sobes.tech IA
Resposta da IA
Vários objetos std::shared_ptr podem referir-se ao mesmo ponteiro graças à existência de um bloco de controlo (control block).
O bloco de controlo associado ao objeto gerido contém:
- Contador de referências fortes (strong reference count): Aumenta ao criar um novo
shared_ptrpara o mesmo objeto. Diminui ao destruir umshared_ptr. Quando chega a zero, o objeto (ponteiro) associado é eliminado. - Contador de referências fracas (weak reference count): Usado para
std::weak_ptr. Aumenta ao criar umweak_ptra partir de umshared_ptr. Diminui ao destruir umweak_ptr. Quando ambos os contadores atingem zero, o bloco de controlo é eliminado. - Ponteiro próprio para o objeto gerido: Não o ponteiro de dados em si, mas aquele que é gerido pelo bloco.
Quando cria um shared_ptr a partir de outro existente (cópia, atribuição-cópia), ambos começam a usar o mesmo bloco de controlo, e o contador de referências fortes nesse bloco aumenta.
Exemplo:
#include <memory>
#include <iostream>
struct MyData {
int value;
MyData(int v) : value(v) { std::cout << "MyData(" << value << ") criado.\n"; }
~MyData() { std::cout << "MyData(" << value << ") destruido.\n"; }
};
int main() {
// Cria o primeiro shared_ptr.
// Cria o bloco de controlo e o objeto MyData.
// Contadores strong: 1, weak: 0.
std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
std::cout << "contagem de uso de ptr1: " << ptr1.use_count() << "\n";
// Cria um segundo shared_ptr a partir de ptr1.
// Usa o mesmo bloco de controlo.
// O contador strong aumenta para 2.
std::shared_ptr<MyData> ptr2 = ptr1;
std::cout << "contagem de uso de ptr1: " << ptr1.use_count() << "\n";
std::cout << "contagem de uso de ptr2: " << ptr2.use_count() << "\n";
// Cria um terceiro shared_ptr a partir de ptr1.
// Usa o mesmo bloco de controlo.
// O contador strong aumenta para 3.
std::shared_ptr<MyData> ptr3 = ptr1;
std::cout << "contagem de uso de ptr1: " << ptr1.use_count() << "\n";
std::cout << "contagem de uso de ptr2: " << ptr2.use_count() << "\n";
std::cout << "contagem de uso de ptr3: " << ptr3.use_count() << "\n";
std::cout << "Sair do escopo.\n";
// ptr3 sai do escopo.
// O contador strong diminui para 2.
// ptr2 sai do escopo.
// O contador strong diminui para 1.
// ptr1 sai do escopo.
// O contador strong diminui para 0.
// O objeto MyData é destruído.
// O bloco de controlo é destruído.
}
Cada objeto shared_ptr contém o seu próprio ponteiro para o bloco de controlo e o seu próprio ponteiro para o objeto de dados. Ao copiar um shared_ptr, ambos os ponteiros são copiados, e o contador de referências fortes no bloco comum é incrementado. Assim, todos os shared_ptr apontam para o mesmo bloco de controlo, que acompanha o número de cópias que possuem o recurso e determina o momento de destruição do recurso gerido.