2014-09-16 19 views
15

Voglio mantenere il comportamento intelligente di std::shared_ptr. Quindi c'è un modo per lanciare un puntatore void condiviso su un altro tipo senza confondere il conteggio dei riferimenti? Non riesco a ottenere il puntatore raw e creare un nuovo puntatore condiviso da esso.C'è un modo per trasmettere shared_ptr <void> a shared_ptr <T>?

+1

Possibile duplicato di http://stackoverflow.com/questions/6795629/how-does-one-downcast-a-stdshared-ptr –

+0

@BillyONeal: No, 'void' non è una classe base di tutti i tipi. Il C++ non è un OO puro. – MSalters

+0

@MSalters: è per questo che ho scritto il commento anziché votare per chiudere (non volevo volerlo fare unilateralmente) –

risposta

20

È possibile utilizzare i cast del puntatore da rob mayoff's answer; ma fa attenzione. E 'facile da innescare involontariamente un comportamento indefinito qui:

struct MyClass {}; 

void* rawPtr = new MyClass; 
shared_ptr<void> exampleVoid(rawPtr); // Undefined behavior; 
             // calls delete (void*)ptr; 

shared_ptr<void> exampleVoidCons(new MyClass); 
    // OK, calls shared_ptr<void>::shared_ptr<MyClass>(MyClass*) which 
    // makes a deleter calling delete (MyClass*)ptr; 

shared_ptr<MyClass> example(new MyClass); // OK, calls delete (MyClass*)ptr; 

shared_ptr<void> castToVoid = static_pointer_cast<void>(example); 
    // OK, shared_ptr's deleter is erased so this still calls delete (MyClass*)ptr; 

In genere questo comportamento indefinito si tradurrà in distruttore del tipo non essere chiamato. Ad esempio, see the output on ideone e nota che la versione inserita in un void* non stampa mai che è stata distrutta.


See C++ 11 5.3.5 [expr.delete]/3:

Nella prima alternativa (cancella oggetto), se il tipo statico dell'oggetto da cancellare è diverso dal suo tipo dinamico, il tipo statico deve essere una classe base del tipo dinamico dell'oggetto da eliminare e il tipo statico deve avere un distruttore virtuale o il comportamento non è definito.

Poiché l'oggetto reale sarà mai un tipo dinamico void, e void è mai una classe di base di tipo dinamico, delete ing un void* innesca comportamento indefinito.

+0

Una versione precedente di questa risposta aveva una porzione 'shared_ptr exampleVoid (new MyClass)' non corretta che ho ora fisso. Sentiti libero di rimuovere i voti per aver messo il mio piede nella mia bocca: P –

+1

+1 per fornire una risposta più completa, riconoscendo anche che hai commesso un errore, ammettendo e correggendo dovrebbe essere incoraggiato, molti di noi sono qui per imparare e questo è parte del processo. –

+1

Sono arrabbiato perché hai cancellato la risposta per la modifica proprio mentre stavo scrivendo un commento sull'esempio errato ;-) –