Conseguir um boost :: shared_ptr para este
Pergunta
Estou fazendo uso extensivo de boost:shared_ptr
no meu código. Na verdade, a maioria dos objetos que são alocados na pilha são realizadas por um shared_ptr
. Infelizmente, isso significa que não posso passar this
em qualquer função que leva um shared_ptr
. Considere este código:
void bar(boost::shared_ptr<Foo> pFoo)
{
...
}
void Foo::someFunction()
{
bar(this);
}
Há dois problemas aqui. Em primeiro lugar, isso não irá compilar porque o T * construtor para shared_ptr
é explícita. Em segundo lugar, se eu forçá-lo a construir com bar(boost::shared_ptr<Foo>(this))
I terá criado um ponteiro segunda compartilhada ao meu objeto que acabará por levar a uma dupla-eliminação.
Isto leva-me à minha pergunta: Existe algum padrão normal para obter uma cópia do ponteiro compartilhada existente você sabe que existe a partir de dentro de um método em um desses objetos? É usando referência intrusiva contando a minha única opção aqui?
Solução
Você pode derivar de enable_shared_from_this e então você pode usar "shared_from_this ()" em vez de "isto" para gerar um ponteiro compartilhada para a sua própria auto objeto.
Exemplo no link:
#include <boost/enable_shared_from_this.hpp>
class Y: public boost::enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
int main()
{
shared_ptr<Y> p(new Y);
shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
É uma boa idéia quando desova tópicos de uma função de membro para boost :: ligam a um shared_from_this () em vez disso. Ele vai garantir que o objeto não é liberado.
Outras dicas
Basta usar um ponteiro bruto para o seu parâmetro de função em vez do shared_ptr. O propósito de um ponteiro inteligente é controlar a vida útil do objeto, mas a vida útil do objeto já está garantida pelo C ++ regras de escopo: existirá, pelo menos enquanto o final de sua função. Ou seja, o código de chamada não pode excluir o objeto antes de seus função retorna; assim, a segurança de um ponteiro "dumb" é garantido, contanto que você não tente excluir o objeto dentro de sua função.
A única vez que você precisa passar um shared_ptr em uma função é quando você quer passar a propriedade do objeto para a função, ou quer a função para fazer uma cópia do ponteiro.
boost tem uma solução para este caso de uso, verifique enable_shared_from_this
Você está realmente fazendo cópias mais comuns de pFoo bar dentro? Se você não está fazendo nada dentro louco, basta fazer o seguinte:
void bar(Foo &foo)
{
// ...
}
Com C ++ 11 shared_ptr
e enable_shared_from_this
está agora na biblioteca padrão. Este último é, como o nome sugere, para este caso exatamente.
http://en.cppreference.com/w/cpp/memory/shared_ptr
http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
bases de exemplo, em que nas ligações acima:
struct Good: std::enable_shared_from_this<Good>{
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
uso:
std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
A função aceitar um ponteiro quer fazer um dos dois comportamentos:
- possui o objeto sendo passado, e excluí-lo quando ele sai do escopo. Neste caso, você pode simplesmente aceitar X * e imediatamente embrulhar um scoped_ptr em torno desse objeto (no corpo da função). Isto irá funcionar para aceitar "isso" ou, em geral, qualquer objeto alocado-heap.
- Compartilhe um ponteiro (não o possui) para o objeto que está sendo passado. Neste caso você não quiser usar um scoped_ptr em tudo, desde que você não quero excluir o objeto no final de sua função. Neste caso, o que teoricamente quer é um shared_ptr (eu vi que chamou de linked_ptr em outros lugares). A biblioteca de impulso tem uma versão do shared_ptr , e este também é recomendado no livro de Scott Meyers' Effective C ++ (ponto 18 na 3ª edição).
Editar: Oops eu descaracterizou um pouco a pergunta, e agora vejo esta resposta não está se dirigindo exatamente a questão. Vou deixá-lo de qualquer maneira, no caso de isso pode ser útil para quem trabalha com código semelhante.