Quando você usar um std :: auto_ptr em vez de boost :: shared_ptr?
-
22-07-2019 - |
Pergunta
Nós praticamente se moveu para usando boost::shared_ptr
em todo o nosso código, no entanto, ainda temos alguns casos isolados, onde usamos std::auto_ptr
, incluindo aulas únicas:
template < typename TYPE >
class SharedSingleton
{
public:
static TYPE& Instance()
{
if (_ptrInstance.get() == NULL)
_ptrInstance.reset(new TYPE);
return *_ptrInstance;
}
protected:
SharedSingleton() {};
private:
static std::auto_ptr < TYPE > _ptrInstance;
};
Eu tenho dito que há uma boa razão por que isso não foi feito um shared_ptr
, mas para a vida de mim eu não consigo entender por quê? Eu sei que auto_ptr
acabará por se marcado como depreciado no próximo padrão, então eu gostaria de sabe o que / como posso substituir essa implementação .
Além disso, existem outras razões por que você iria considerar o uso de um auto_ptr
em vez de um shared_ptr
? E você vê nenhum problema de se mudar para shared_ptr no futuro?
Editar:
- Assim, em resposta à pergunta "posso com segurança substituir
auto_ptr
comshared_ptr
no código acima", a resposta é sim -. No entanto eu vou ter um pequeno impacto no desempenho - Quando
auto_ptr
eventualmente é marcado como depreciado e nós passar parastd::shared_ptr
, vamos precisar para testar exaustivamente o nosso código para se certificar de que estamos respeitando as diferentes semântica de propriedade.
Solução
auto_ptr
e shared_ptr
resolver completamente diferentes problemas. Um não substitui o outro.
auto_ptr
é um wrapper fino ao redor ponteiros para implementar RAII semântica, para que os recursos são sempre liberados , mesmo diante exceções. auto_ptr
não executa nenhuma contagem de referência ou similares em tudo, não faz vários ponteiros apontam para o mesmo objeto ao criar cópias. Na verdade, é muito diferente. auto_ptr
é uma das poucas classes, onde o operador de atribuição modifica o origem objeto. Considere este plug descarado do auto_ptr wikipedia página :
int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;
y = x;
cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i
Observe como executar
y = x;
modifica não só y mas também x.
O modelo boost::shared_ptr
torna mais fácil de lidar com vários ponteiros para o mesmo objeto, e o objeto só é eliminado após a última referência a ele saiu do escopo. Este recurso não é útil em seu cenário, que (tentativas de) implementar um Singleton . No seu cenário, há sempre quer 0 referências a 1 de referência para o único objeto da classe, se for o caso.
Em essência, objetos auto_ptr
e objetos shared_ptr
têm completamente diferentes semântica (é por isso que você não pode usar o antigo em recipientes, mas fazê-lo com o último é bom), e eu com certeza espero que você tenha bons testes para capturar qualquer regressões você introduzidas enquanto portar seu código. : -}
Outras dicas
Outros têm respondido por que esse código usa um auto_ptr
em vez de um shared_ptr
. Para lidar com suas outras perguntas:
O que / como posso substituir essa implementação?
Use quer boost::scoped_ptr
ou unique_ptr
(disponível tanto em Boost e o novo C ++ padrão). Ambos scoped_ptr
e unique_ptr
fornecer propriedade estrito (e nenhuma sobrecarga de contagem de referência), andthey evitar os surpreendentes semântica delete-on-copy de auto_ptr
.
Além disso, existem outras razões por que você iria considerar o uso de um auto_ptr
em vez de um shared_ptr
? E você vê nenhum problema de se mudar para shared_ptr
no futuro?
Pessoalmente, eu não iria usar um auto_ptr
. Excluir-on-cópia é muito não-intuitivo. Herb Sutter parece concordar . Mudar para scoped_ptr
, unique_ptr
, ou shared_ptr
deve oferecer nenhum problema. Especificamente, shared_ptr
deve ser um substituto se você não se preocupam com a sobrecarga de contagem de referência. scoped_ptr
é um substituto se você não estiver usando recursos de transferência de propriedade de auto_ptr
. Se você estiver usando a transferência de propriedade, então unique_ptr
é quase um substituto, exceto que você precisa chamar em vez explicitamente move
para transferir a propriedade. Consulte aqui para um exemplo.
auto_ptr é o único tipo de uso inteligente ponteiro I. Eu usá-lo porque eu não usar Boost, e porque eu geralmente preferem meus negócios aulas / orientadas para a aplicação explicitamente definir semântica de deleção e ordem, ao invés de depender coleções de, ou, ponteiros inteligentes individuais.