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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top