Domanda

Sto facendo ampio uso di boost:shared_ptr nel mio codice. In effetti, la maggior parte degli oggetti allocati nell'heap sono trattenuti da un shared_ptr. Purtroppo questo significa che non riesco a passare this in nessuna funzione che accetta un bar(boost::shared_ptr<Foo>(this)). Considera questo codice:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

Ci sono due problemi qui. Innanzitutto, questo non verrà compilato perché il costruttore T * per <=> è esplicito. In secondo luogo, se lo costringo a compilare con <=> avrò creato un secondo puntatore condiviso al mio oggetto che alla fine porterà a una doppia eliminazione.

Questo mi porta alla mia domanda: esiste un modello standard per ottenere una copia del puntatore condiviso esistente che sai esiste all'interno di un metodo su uno di quegli oggetti? L'uso del riferimento invadente conta la mia unica opzione qui?

È stato utile?

Soluzione

Puoi derivare da enable_shared_from_this e poi tu può usare " shared_from_this () " invece di " questo " per generare un puntatore condiviso al proprio oggetto personale.

Esempio nel collegamento:

#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
}

È una buona idea quando si generano thread da una funzione membro per boost :: bind a shared_from_this () invece di questo. Garantirà che l'oggetto non venga rilasciato.

Altri suggerimenti

Basta usare un puntatore non elaborato per il parametro della funzione invece di shared_ptr. Lo scopo di un puntatore intelligente è di controllare la durata dell'oggetto, ma la durata dell'oggetto è già garantita dalle regole di ambito C ++: esisterà almeno fino alla fine della funzione. Cioè, il codice chiamante non può assolutamente cancellare l'oggetto prima che la tua funzione ritorni; quindi la sicurezza di un " dumb " il puntatore è garantito, purché non si tenti di eliminare l'oggetto all'interno della propria funzione.

L'unica volta che è necessario passare un shared_ptr in una funzione è quando si desidera passare la proprietà dell'oggetto alla funzione o si desidera che la funzione esegua una copia del puntatore.

boost ha una soluzione per questo caso d'uso, controlla enable_shared_from_this

Stai davvero realizzando più copie condivise di pFoo all'interno della barra? Se non stai facendo niente di folle dentro, fai questo:


void bar(Foo &foo)
{
    // ...
}

Con C ++ 11 shared_ptr e enable_shared_from_this è ora nella libreria standard. Quest'ultimo è, come suggerisce il nome, per questo caso esattamente.

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

L'esempio si basa su quello nei link sopra:

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

utilizzo:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';

La funzione che accetta un puntatore vuole fare uno dei due comportamenti:

  • Possiedi l'oggetto che viene passato ed eliminalo quando esce dall'ambito. In questo caso, puoi semplicemente accettare X * e avvolgere immediatamente scoped_ptr attorno a quell'oggetto (nel corpo della funzione). Questo funzionerà per accettare & Quot; questo & Quot; o, in generale, qualsiasi oggetto allocato in heap.
  • Condividi un puntatore (non possederlo) sull'oggetto che viene passato. In questo caso non vuoi usare affatto un scoped_ptr, dato che tu non voglio cancellare l'oggetto al termine della tua funzione. In questo caso, ciò che teoricamente vuoi è un shared_ptr (l'ho visto chiamato Linked_ptr altrove). La libreria boost ha una versione di shared_ptr e questo è raccomandato anche nell'efficace libro C ++ di Scott Meyers (articolo 18 della 3a edizione).

Modifica: Spiacenti, ho letto male la domanda e ora vedo che questa risposta non risponde esattamente alla domanda. Lo lascerò comunque, nel caso in cui questo possa essere utile per chiunque lavori su un codice simile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top