Wydaje się, że zarówno static_cast, jak i reinterpret_cast działają dobrze w przypadku rzutowania void * na inny typ wskaźnika. Czy istnieje dobry powód, aby faworyzować jednego nad drugim?
202
Wydaje się, że zarówno static_cast, jak i reinterpret_cast działają dobrze w przypadku rzutowania void * na inny typ wskaźnika. Czy istnieje dobry powód, aby faworyzować jednego nad drugim?
Odpowiedzi:
Zastosowanie
static_cast
: jest to najwęższa obsada, która dokładnie opisuje dokonaną tutaj konwersję.Istnieje błędne przekonanie, że użycie
reinterpret_cast
byłoby lepsze, ponieważ oznacza „całkowicie zignoruj bezpieczeństwo typu i po prostu rzuć z A na B”.Jednak tak naprawdę nie opisuje to efektu
reinterpret_cast
. Raczejreinterpret_cast
ma wiele znaczeń, z których wszystkie utrzymują, że „wykonywane mapowaniereinterpret_cast
jest zdefiniowane w ramach implementacji”. [5.2.10.3]Ale w szczególności przypadku odlewania z
void*
doT*
mapowania jest zupełnie dobrze zdefiniowane przez standard; mianowicie, aby przypisać typ do wskaźnika bez typu, bez zmiany jego adresu.To jest powód, aby preferować
static_cast
.Ponadto, i prawdopodobnie ważniejsze, jest fakt, że każde użycie
reinterpret_cast
jest wręcz niebezpieczne, ponieważ przekształca wszystko w cokolwiek innego (w przypadku wskaźników), podczas gdystatic_cast
jest znacznie bardziej restrykcyjne, zapewniając w ten sposób lepszy poziom ochrony. To już uratowało mnie przed błędami, w których przypadkowo próbowałem zmusić jeden typ wskaźnika do drugiego.źródło
To trudne pytanie. Z jednej strony Konrad doskonale rozumie definicję specyfikacji dla reinterpret_cast , chociaż w praktyce prawdopodobnie robi to samo. Z drugiej strony, jeśli używasz rzutowania między typami wskaźników (co jest dość powszechne, na przykład podczas indeksowania w pamięci za pomocą znaku char *), static_cast wygeneruje błąd kompilatora i będziesz zmuszony użyć reinterpret_cast .
W praktyce używam reinterpret_cast, ponieważ jest to bardziej opisowe zamiar operacji rzutowania. Z pewnością możesz uzasadnić, że inny operator wyznaczy tylko reinterpretację wskaźnika (co gwarantowało zwrot tego samego adresu), ale nie ma takiego w standardzie.
źródło
reinterpret_cast
!Zawsze sugeruję używanie najsłabszej możliwej obsady.
reinterpret_cast
może być użyty do rzutowania wskaźnika nafloat
. Im bardziej rzutuje się na strukturę, tym więcej uwagi wymaga jej użycie.W przypadku
char*
używałbym rzutowania w stylu c, dopóki nie będziemy mielireinterpret_pointer_cast
, ponieważ jest on słabszy i nic więcej nie jest wystarczające.źródło
float f = *reinterpret_cast<const float*>(&p);
float
, co jest fałszem. Odlewy ekspresyjnevoid **
doconst float *
, a następnie używa operację wyłuskiwania (co nie jest odlew), aby przekształcićconst float *
sięfloat
.Moje osobiste preferencje oparte są na umiejętności pisania kodu:
lub
Oba robią to samo na końcu, ale static_cast wydaje się bardziej odpowiednie w środowisku aplikacji, podczas gdy reinterpretacja obsady wydaje się bardziej jak coś, co można zobaczyć w bibliotece niższego poziomu IMHO.
źródło