2014-09-16 24 views
15

Chcę zachować inteligentne zachowanie std::shared_ptr. Czy istnieje sposób na przesłanie współdzielonego wskaźnika pustego pola do innego typu, nie myląc jednocześnie licznika odwołań? Nie mogę uzyskać surowego wskaźnika i utworzyć z niego nowego udostępnionego wskaźnika.Czy istnieje sposób na przesłanie pliku shared_ptr <void> do shared_ptr <T>?

+1

Możliwe duplikaty http://stackoverflow.com/questions/6795629/how-does-one-downcast-a-stdshared-ptr –

+0

@BillyONeal: Nie, 'void' nie jest podstawową klasą wszystkich typów. C++ nie jest takim czystym OO. – MSalters

+0

@MSalters: to dlatego napisałem komentarz zamiast faktycznego głosowania na zamknięcie (nie chciałem tego robić jednostronnie) –

Odpowiedz

20

Możesz użyć wskaźnika odlewania z rob mayoff's answer; ale bądź ostrożny. Łatwo jest nieumyślnie spowodować niezdefiniowane zachowanie tutaj:

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; 

Zazwyczaj niezdefiniowane zachowanie doprowadzi destructor na typ nie miano. Na przykład see the output on ideone i pamiętaj, że wersja umieszczona w void* nigdy nie drukuje, że została zniszczona.


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

W pierwszym przypadku (usuwanie Object), w przypadku statycznego obiektu na który ma być usunięty różni od typu dynamicznego typ statyczny jest klasą podstawową typu dynamicznego obiektu, który ma być usunięty, a typ statyczny powinien mieć wirtualny destruktor lub zachowanie jest niezdefiniowane.

Ponieważ rzeczywisty obiekt nie będzie miał dynamiczny typ void i void nigdy nie jest klasa bazowa typu dynamicznego, delete ing void* wyzwala niezdefiniowanej zachowanie.

+0

Poprzednia wersja tej odpowiedzi miała niepoprawną 'shared_ptr exampleVoid (new MyClass)' część, którą mam teraz naprawiony. Zapraszam do usunięcia przegranych za włożenie stopy do buzi: P –

+1

+1 za udzielenie pełniejszej odpowiedzi, także uznanie, że popełniłeś błąd, przyznając się i naprawiając powinno być zachęcane, większość z nas jest tutaj, aby się uczyć i to jest część procesu. –

+1

Jestem krzyżykiem, ponieważ usunąłeś odpowiedź do edycji właśnie podczas pisania komentarza dotyczącego niewłaściwego przykładu ;-) –