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>?
Odpowiedz
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.
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 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. –
Jestem krzyżykiem, ponieważ usunąłeś odpowiedź do edycji właśnie podczas pisania komentarza dotyczącego niewłaściwego przykładu ;-) –
Możesz użyć std::static_pointer_cast
lub std::dynamic_pointer_cast
w zależności od rodzaju obsady.
Możliwe duplikaty http://stackoverflow.com/questions/6795629/how-does-one-downcast-a-stdshared-ptr –
@BillyONeal: Nie, 'void' nie jest podstawową klasą wszystkich typów. C++ nie jest takim czystym OO. – MSalters
@MSalters: to dlatego napisałem komentarz zamiast faktycznego głosowania na zamknięcie (nie chciałem tego robić jednostronnie) –