C++ shared_ptr vs.unique_ptr para a gestão dos recursos
-
21-12-2019 - |
Pergunta
Estive meditando sobre o uso de unique_ptr
vs shared_ptr
vs own_solution
.Eu já descontado o último, como eu vou quase certamente ser errado, mas eu tenho um problema com ambos unique_ptr
e shared_ptr
em que nem capta precisamente o que eu quero.Eu quero criar um gerenciador de recursos que explicitamente possui um recurso, no entanto, eu gostaria que o gerenciador de recursos de mão também as referências para o recurso.
Se eu usar unique_ptr
no gerenciador de recursos e mão matérias ponteiros há a possibilidade de que possam escapar em outro lugar (apesar de que isso seria contra a classe "contrato" eu suponho).Se eu usar shared_ptr
e do lado de fora weak_ptr
, não há nada que impeça um chamador de converter o weak_ptr
para um shared_ptr
e armazenamento de que, potencialmente, assim, a criação de um ciclo ou, pior ainda, um recurso que vivem além do tempo de vida do gestor de recursos.Então eu suponho que o que eu estou procurando é uma deferencable weak_ptr
que não pode ser convertida em shared_ptr
.
Ou estou apenas olhando para executar o contrato com alguns fortemente redigida comentários no código?
Obrigado por todos os pensamentos que você pode ter sobre isso.
Solução
Ponteiros inteligentes como shared_ptr
e unique_ptr
são boas ferramentas quando você tem possuir ponteiros.
Mas, por não possuir ponteiros, i.é. observando os ponteiros, usando um ponteiro bruto é apenas multa.
Em seu design, eu acho que o gestor de recursos é o único "dono" de recursos, então você poderia simplesmente ter alguma forma de ponteiro inteligente dentro o gerenciador de recursos.Por exemplo, o gerenciador de recursos pode ter um std::vector<std::unique_ptr<Resource>>
como um membro de dados, ou até mesmo um mais simples std::vector<Resource>
se o seu Resource
classe é projetado para ser corretamente armazenados em um std::vector
.
Em seguida, o gerenciador de recursos pode dar para o exterior só não possuir observando os ponteiros, e matérias de apontadores (ou C++ referências) são bons para este caso.
Claro, é importante que o tempo de vida do gerenciador de recursos de não exceder a dos "recursos de clientes".
Outras dicas
No final, você não pode forçar ninguém a ouvir.Pergunte a microsoft, apple ou qualquer biblioteca de código aberto do desenvolvedor, todos sabem que música.Um comentário em as palavras certas e lugares é a sua melhor aposta.
Evitar a criação de seu próprio ponteiro inteligente de classe, impede composição e reduz a legibilidade.Como último recurso, tente procurar no impulso, ou qualquer framework de código já tem para trabalhar.
Se você tem não-proprietários, eles são elegíveis para a realização de weak_ptr
s ou (se é garantido para permanecer válido para a duração) matérias ponteiros.
Se você usar shared_ptr
s internamente (por que você deve), melhor prestação de weak_ptr
prima e de ponteiros.
Todos os ponteiros inteligentes explicitamente indicar uma política de propriedade.Matérias ponteiros denotar nenhum ou não possuir.
auto_ptr
:Não use, preterido com muitas armadilhas, mesmo para o cuidado.unique_ptr
:Propriedade exclusiva.shared_ptr
:Propriedade compartilhadaweak_ptr
:Nenhum direito de propriedade, podem ser suprimido por trás de suas costas.- matérias ponteiro
- Explicitamente não há propriedade com garantia de maior vida útil
- ou manual de gerenciamento de propriedade.
Então eu suponho que o que eu estou procurando é uma deferencable weak_ptr que não pode ser convertido em um shared_ptr.
Você poderia entregar a sua pequena classe auxiliar:
template<typename T>
class NonConvertibleWeakPtr
{
public:
NonConvertibleWeakPtr(const std::shared_ptr<T>& p) : p_(p) {}
... // other constructors / assignment operators
bool expired() const { return p_.expired(); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
private:
T* get() const { return p_.lock().get(); }
private:
std::weak_ptr<T> p_;
};
Este é um pouco melhor do que uma matéria-prima de ponteiro, porque você pode verificar se o ponteiro ainda é válido.
Exemplo de uso:
std::shared_ptr<int> sp = std::make_shared<int>(5);
{
NonConvertibleWeakPtr<int> wp(sp);
if(!wp.expired()) {
std::cout << *wp << std::endl;
}
}
No entanto, um usuário pode ainda mau uso como, por exemplo, com std::shared_ptr<T> blah(&(*wp));
, mas é preciso um pouco mais de criminal de energia.