Static_cast ve reinterpret_cast, void * 'i başka bir işaretçi türüne dönüştürmek için iyi çalışıyor gibi görünüyor. Birini diğerine tercih etmek için iyi bir neden var mı?
Static_cast ve reinterpret_cast, void * 'i başka bir işaretçi türüne dönüştürmek için iyi çalışıyor gibi görünüyor. Birini diğerine tercih etmek için iyi bir neden var mı?
Yanıtlar:
Kullanımstatic_cast
: Burada hangi dönüşümün yapıldığını tam olarak tanımlayan en dar dökümdür.
Kullanmanın reinterpret_cast
daha iyi bir eşleşme olacağına dair bir yanlış kanı vardır, çünkü “tip güvenliği tamamen göz ardı etmek ve sadece A'dan B'ye atmak” anlamına gelir.
Ancak, bu aslında a'nın etkisini tanımlamaz reinterpret_cast
. Aksine, birçoğunun reinterpret_cast
anlamı, “gerçekleştirdiği eşlemenin reinterpret_cast
uygulama tarafından tanımlandığı” anlamına gelir. [5.2.10.3]
Ancak yayın yapmak özel durumda void*
için T*
eşleme standart tarafından iyi tanımlanmış olduğu; yani, adresini değiştirmeden tipsiz bir işaretçiye bir tür atamak.
Bu tercih sebebidir static_cast
.
Ayrıca ve tartışmasız daha da önemlisi, her kullanımının reinterpret_cast
düpedüz tehlikeli olması, çünkü static_cast
çok daha kısıtlayıcı olmakla birlikte daha iyi bir koruma sağlaması nedeniyle herhangi bir şeyi gerçekten (işaretçiler için) dönüştürür . Bu beni yanlışlıkla bir işaretçi türünü diğerine zorlamaya çalıştığım hatalardan kurtardı.
Bu zor bir soru. Bir yandan, Konrad reinterpret_cast için spec tanımı hakkında mükemmel bir noktaya işaret ediyor , ancak pratikte muhtemelen aynı şeyi yapıyor. Öte yandan, işaretçi türleri arasında yayın yapıyorsanız (örneğin, bir char * aracılığıyla bellekte dizin oluştururken oldukça yaygındır), static_cast bir derleyici hatası oluşturur ve yine de reinterpret_cast'i kullanmak zorunda kalırsınız .
Uygulamada reinterpret_cast kullanıyorum çünkü döküm işleminin amacını daha açıklayıcı. Farklı bir operatörün yalnızca işaretçi yeniden yorumlamalarını (aynı adresin döndürülmesini garanti eden) belirtmesi için kesinlikle bir dava açabilirsiniz, ancak standartta bir tane yoktur.
reinterpret_cast
!
Her zaman mümkün olan en zayıf oyuncu kadrosunu kullanmanızı öneririm.
reinterpret_cast
bir işaretçiyi a float
. Döküm ne kadar fazla yapı kırılırsa, o kadar fazla dikkat gerektirir.
Bu durumda, char*
biraz bulana kadar c tarzı döküm kullanırım reinterpret_pointer_cast
, çünkü daha zayıf ve başka hiçbir şey yeterli değil.
float f = *reinterpret_cast<const float*>(&p);
float
, bu yanlıştır. İfadesi alçılar void **
için const float *
daha sonra ve dönüştürmek için, bir KQUEUE operasyonu (dökme DEĞİL olan) kullandığı const float *
için float
.
Kişisel tercihim şöyle kod okuryazarlığına dayanıyor:
void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();
veya
typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();
Her ikisi de sonunda aynı şeyi yapıyor, ancak static_cast bir orta eşya, uygulama ortamında daha uygun görünüyorken, cast'ı yeniden yorumlamak daha düşük seviyeli bir IMHO kütüphanesinde göreceğiniz bir şeye benziyor.