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
Odpowiedz
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.
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.
"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
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.
Drugi przykładowy kod nie zostanie skompilowany. –
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.
"_reinterpret_cast może być użyty do rzucania wskaźnika na float." "Z pewnością nie! – curiousguy
z pewnością tak, curiousguy. Sprawdź ponownie standard. –
Czy możesz podać przykład? – curiousguy
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. –
@on Wygląda na to, że nigdy wcześniej nie pracowałeś z wątkami POSIX. – user470379
@ user470379 Wow ... właśnie dlatego wylądowałem na to pytanie w SO! Doskonała obserwacja :-). –