Baik static_cast dan reinterpret_cast tampaknya berfungsi dengan baik untuk membuang void * ke jenis pointer lain. Apakah ada alasan bagus untuk lebih menyukai yang satu dari yang lain?
Baik static_cast dan reinterpret_cast tampaknya berfungsi dengan baik untuk membuang void * ke jenis pointer lain. Apakah ada alasan bagus untuk lebih menyukai yang satu dari yang lain?
Jawaban:
Gunakanstatic_cast
: ini adalah pemeran tersempit yang menggambarkan dengan tepat konversi apa yang dibuat di sini.
Ada kesalahpahaman bahwa menggunakan reinterpret_cast
akan menjadi pertandingan yang lebih baik karena itu berarti "sama sekali mengabaikan keselamatan jenis dan hanya melemparkan dari A ke B".
Namun, ini sebenarnya tidak menggambarkan efek dari a reinterpret_cast
. Sebaliknya, reinterpret_cast
memiliki sejumlah makna, yang kesemuanya berpendapat bahwa "pemetaan yang dilakukan oleh reinterpret_cast
didefinisikan-implementasi." [5.2.10.3]
Tetapi dalam kasus khusus casting dari void*
ke T*
pemetaan sepenuhnya didefinisikan dengan baik oleh standar; yaitu, untuk menetapkan tipe ke pointer tanpa typeless tanpa mengubah alamatnya.
Ini adalah alasan untuk memilih static_cast
.
Selain itu, dan bisa dibilang lebih penting, adalah kenyataan bahwa setiap penggunaan reinterpret_cast
benar-benar berbahaya karena mengubah apa pun menjadi hal lain benar-benar (untuk petunjuk), sementara static_cast
jauh lebih ketat, sehingga memberikan tingkat perlindungan yang lebih baik. Ini sudah menyelamatkan saya dari bug di mana saya tidak sengaja mencoba memaksa satu jenis pointer ke yang lain.
Ini adalah pertanyaan yang sulit. Di satu sisi, Konrad membuat poin yang sangat baik tentang definisi spesifikasi untuk reinterpret_cast , meskipun dalam praktiknya mungkin melakukan hal yang sama. Di sisi lain, jika Anda melakukan casting di antara tipe pointer (seperti yang biasa terjadi saat pengindeksan dalam memori melalui char *, misalnya), static_cast akan menghasilkan kesalahan kompiler dan Anda akan dipaksa untuk menggunakan reinterpret_cast pula.
Dalam praktiknya saya menggunakan reinterpret_cast karena lebih deskriptif tentang maksud operasi pemeran. Anda tentu bisa membuat kasus untuk operator yang berbeda untuk menunjuk penafsiran ulang pointer saja (yang menjamin alamat yang sama dikembalikan), tetapi tidak ada satu pun dalam standar.
reinterpret_cast
!
Saya sarankan menggunakan pemain terlemah yang mungkin selalu.
reinterpret_cast
dapat digunakan untuk melemparkan pointer ke a float
. Semakin banyak pemecah struktur yang dilemparkan, semakin banyak perhatian yang dibutuhkan.
Dalam hal char*
, saya akan menggunakan pemeran c-style, sampai kita memiliki beberapa reinterpret_pointer_cast
, karena itu lebih lemah dan tidak ada lagi yang cukup.
float f = *reinterpret_cast<const float*>(&p);
float
, yang salah. Ekspresi gips void **
untuk const float *
, dan kemudian menggunakan operasi dereference (yang TIDAK gips), untuk mengkonversi const float *
ke float
.
Preferensi pribadi saya didasarkan pada literasi kode seperti ini:
void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();
atau
typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();
Mereka berdua melakukan hal yang sama pada akhirnya, tetapi static_cast tampaknya lebih tepat di lingkungan aplikasi menengah, sementara menafsirkan kembali para pemain sepertinya lebih seperti yang Anda lihat di IMHO perpustakaan tingkat rendah.