2008-11-21 9 views
144

Zarówno static_cast, jak i reinterpret_cast, wydają się działać dobrze, aby rzutować void * na inny typ wskaźnika. Czy istnieje dobry powód, by faworyzować jedną nad drugą?Powinieneś użyć static_cast lub reinterpret_cast podczas rzutowania pustki * na cokolwiek

+3

Lepsze pytanie brzmiałoby: "Jak uniknąć używania wskaźników pustych w moim kodzie?". Nie jest to trudne - nie pamiętam, kiedy ostatnio go używałem. –

+60

@on Wygląda na to, że nigdy wcześniej nie pracowałeś z wątkami POSIX. – user470379

+3

@ user470379 Wow ... właśnie dlatego wylądowałem na to pytanie w SO! Doskonała obserwacja :-). –

Odpowiedz

88

Użyj static_cast: jest to najwęższa obsada, która dokładnie opisuje, co tutaj się dokonuje.

Istnieje błędne przekonanie, że użycie reinterpret_cast byłoby lepszym rozwiązaniem, ponieważ oznacza "całkowite zignorowanie bezpieczeństwa typu i po prostu rzutowanie od A do B".

To jednak nie opisuje efektu reinterpret_cast. Raczej reinterpret_cast ma wiele znaczeń, dla wszystkich, które głosi, że „mapowanie wykonywane przez reinterpret_cast jest realizacja zdefiniowane.” [5.2.10.3]

Jednak w szczególnym przypadku odlewania z void* do T* odwzorowanie jest całkowicie dobrze zdefiniowany przez standard; mianowicie, aby przypisać typ wskaźnikowi beztekstowemu bez zmiany jego adresu.

Jest to powód, aby preferować static_cast. Dodatkowo, i prawdopodobnie ważniejsze, jest to, że każde użycie reinterpret_cast jest wręcz niebezpieczne, ponieważ konwertuje wszystko na cokolwiek innego (na wskaźniki), podczas gdy static_cast jest znacznie bardziej restrykcyjne, co zapewnia lepszy poziom ochrony. To już uratowało mnie od błędów, w których przypadkowo próbowałem przymusić jeden typ wskaźnika do drugiego.

5

To jest trudne pytanie. Z jednej strony, Konrad znakomicie wskazuje na definicję specyfikacji dla reinterpret_cast, chociaż w praktyce prawdopodobnie robi to samo. Z drugiej strony, jeśli rzutujesz między typami wskaźników (co jest dość powszechne, gdy na przykład indeksujesz w pamięci za pomocą znaku *), static_cast wygeneruje błąd kompilatora i będziesz zmuszony użyć reinterpret_cast tak czy inaczej.

W praktyce używam reinterpret_cast, ponieważ jest bardziej opisowy w stosunku do operacji rzutowania. Z pewnością można stworzyć argumenty dla innego operatora, który wskaże tylko reinterpretację wskaźnika (co gwarantuje zwrócenie tego samego adresu), ale nie ma go w standardzie.

+6

"różny operator, który wskaże tylko samą reinterpretację wskaźnika (co gwarantuje zwrócenie tego samego adresu) _" Przytulić? Ten operator ** to ** 'reinterpret_cast'! – curiousguy

-2

Moje osobiste preferencje jest na podstawie kodu umiejętności jak ta:

void* data = something; 
MyClass* foo = reinterpret_cast<MyClass*>(data); 
foo->bar(); 

lub

typedef void* hMyClass; //typedef as a handle or reference 
hMyClass = something; 
const MyClass& foo = static_cast<MyClass&>(*hMyClass); 
foo.bar(); 

Obaj zrobić to samo w końcu, ale static_cast wydaje się bardziej odpowiednie w środkowym-Ware, Środowisko aplikacji, a ponowne zinterpretowanie oddania wydaje się bardziej podobne do tego, co zobaczysz w bibliotece IMHO na niższym poziomie.

+4

Drugi przykładowy kod nie zostanie skompilowany. –

2

Proponuję zawsze używać najsłabszej możliwej obsady.

reinterpret_cast służy do rzutowania wskaźnika na float. Im bardziej struktura jest przełamująca, tym więcej uwagi wymaga jego użycie.

W przypadku char *, używałbym rzutowania w stylu c, dopóki nie mamy reinterpret_pointer_cast, ponieważ jest słabszy i nic więcej nie jest wystarczające.

+0

"_reinterpret_cast może być użyty do rzucania wskaźnika na float." "Z pewnością nie! – curiousguy

+0

z pewnością tak, curiousguy. Sprawdź ponownie standard. –

+0

Czy możesz podać przykład? – curiousguy

Powiązane problemy