Como é que um ponteiro trabalho de contagem de referência smart-contagem de referência?
-
05-09-2019 - |
Pergunta
Em outras palavras, como é que a implementação mantém o controle da contagem?
Existe um mapa-como objeto mantido que é acessível por todas as instâncias shared_ptr
cuja chave é o endereço e o valor do ponteiro é o número de referências? Se eu tenho que implementar um shared_ptr
, esta é a primeira idéia que vem à minha mente.
Existe uma possibilidade de um vazamento de memória no caso de estes ponteiros inteligentes de contagem de referência? Se sim, como posso evitá-los?
Solução
Eu vi duas abordagens não-intrusivas diferentes para isso:
- O ponteiro inteligente aloca uma pequena bloco de memória para conter o contador de referência. Cada cópia do ponteiro inteligente, em seguida, recebe uma apontador para o objecto real e um ponteiro para a contagem de referência.
- Além de um ponteiro de objeto, cada ponteiro inteligente contém um anterior e seguinte ponteiro, assim formando uma lista duplamente ligado de ponteiros inteligentes para um determinado objeto. A contagem de referência é implícita na lista. Quando um inteligente ponteiro é copiado, ele adiciona-se a a lista. Após a destruição, cada ponteiro inteligente remove próprio a lista. Se ele é o último em a lista que, em seguida, libera o objeto referenciado também.
Se você vai aqui e vá até a parte inferior, há uma excelente diagrama que explica esses métodos muito mais claramente.
Outras dicas
Criação de um vazamento de memória com ponteiros inteligentes de contagem de referência é muito fácil. Apenas criar qualquer estrutura gráfico do tipo de objectos que tem um ciclo no gráfico. Os objectos no ciclo irá impedir o outro de ser libertado. Isso não pode ser resolvido automaticamente -. Por exemplo, quando você cria uma lista-link duplo você tem que tomar cuidado de não remover mais de um objeto de cada vez
Cada objeto ponteiro inteligente contém uma contagem de referência compartilhada -. Um para cada ponteiro bruto
Você poderia dar uma olhada este artigo . Esta implementação armazena estes em um objeto separado que é copiado ao redor. Você também pode dar uma olhada em documentação do impulso ou dê uma olhada na Wikipedia artigo sobre ponteiros inteligentes.
No. shared_ptr apenas manter um ponteiro adicional para contagem de referência.
Quando você faz cópia do objeto shared_ptr que copiar ponteiro com contagem de referências, aumentá-lo e copiar ponteiro no objeto contido.
Tanto quanto Lembro-me, houve o problema de ponteiro de contagem de referência tratado em um capítulo de Effective C ++.
Em princípio, você tem a classe ponteiro "light", que contém um ponteiro para uma classe segurando a referência que sabe para aumentar / diminuir de referência e destruir o objeto ponteiro. Que os pontos de classe contagem de referência para o objeto a ser referenciado.
Muitas respostas abordar a forma como a contagem de referência é armazenado (ele é armazenado em uma memória compartilhada para todos shared_ptr que mantenha o mesmo ponteiro nativo), mas a maioria iludir o problema de vazamentos.
A maneira mais fácil de vazamento de memória com referência contada ponteiros é a criação de ciclos. Como exemplo, uma lista duplamente ligada onde todos os ponteiros são shared_ptr com pelo menos dois elementos é garantido para não ser eliminado. Mesmo se ponteiros externos são liberados, os ponteiros internos ainda vai contar, e a contagem de referência não atingirá 0. Isto é, pelo menos, com a implementação mais ingênuo.
A solução mais fácil para o problema ciclo é misturar shared_ptr (referência contada ponteiros) com ponteiros fracos que não compartilham a propriedade do objeto.
ponteiros compartilhados irá compartilhar tanto o recurso (ponteiro) ea informação REFERENCE_COUNT adicional. Quando você usa ponteiros fracos, a contagem de referência é dobrada: há uma contagem de referência ponteiro compartilhada e uma contagem de referência ponteiro fraco. O recurso é liberado quando a contagem ponteiro compartilhada chega a 0, mas a informação REFERENCE_COUNT é deixado vivo até o último ponteiro fraco é liberado.
Na lista duplamente ligada, a referência externa é realizada em um shared_ptr, enquanto que as ligações internas são apenas weak_ptr. Sempre que não há referências externas (shared_ptr) os elementos da lista são liberados, excluir as referências fracas. No final todas as referências fracas foram apagados eo último ponteiro fraco para cada um dos recursos libera as informações REFERENCE_COUNT.
É menos confuso do que o texto acima parece ... Vou tentar novamente mais tarde.