まず第一に、これは「Why do we have reinterpret_cast in C++ when two chained static_cast can do it's job?」の複製ではありません。.
static_cast
それを達成するために2つのチェーンを使用することさえできない状況を私は知ってreinterpret_cast
います。しかしstatic_cast
、シンプルで読みやすいreinterpret_cast
.
まず第一に、これは「Why do we have reinterpret_cast in C++ when two chained static_cast can do it's job?」の複製ではありません。.
static_cast
それを達成するために2つのチェーンを使用することさえできない状況を私は知ってreinterpret_cast
います。しかしstatic_cast
、シンプルで読みやすいreinterpret_cast
.
reinterpret_cast
THIS LOOKS CRAZY BUT I KNOW WHAT I'M DOING という巨大な点滅シンボルである必要があります。怠惰からそれを使用しないでください。
reinterpret_cast
「これらのビットを次のように扱う」ことを意味します。継承ラティスに従ってターゲットを変更する可能性があるため、チェーンされた静的キャストは同じではありません。
struct A {
int x;
};
struct B {
int y;
};
struct C : A, B {
int z;
};
C c;
A * a = &c;
int main () {
assert (reinterpret_cast <B *> (a) != static_cast <B *> (static_cast <C *> (a)));
}
a
が を指していることを 100% 確信できない場合は、 which をb
使用dynamic_cast
して上記のソリューションを検索します (ランタイム コストはかかりますが)。これは NULL を返すか、失敗するとスローされる可能性があることに注意してください。
実際に を使用したときのことを考えようとしていますがreinterpret_cast
、実際には 2 つしかありません。
const char *
それをトラバースするために a を使用したい場合if(*reinterpret_cast<uint32_t*>(array_of_4_bytes_A) < *reinterpret_cast<uint32_t*>(array_of_4_bytes_B)
または何か。このような行は精査を促し、コメントを要求します。それ以外の場合、A*
実際に a であるa がある場合は、B*
おそらく共用体が必要です。
私はいつでも、あるいはいつでも見たいと思ってreinterpret_cast <TargetType> (pointer_of_some_other_type)
いstatic_cast <TargetType> (static_cast <void*> (pointer_of_some_other_type))
ますstatic_cast <TargetType> ((void*) (pointer_of_some_other_type))
。void *を通過するキャストのチェーンは、恐ろしいreinterpret_castの使用を回避するための、卑劣で手に負えない方法にすぎません。
多くのプロジェクトでは、免除が認められない限り、reinterpret_castの使用を禁止しています。コードを書いた人は、キャストの使用を正当化する必要があります。IMO、静的キャストのチェーンはreinterpret_castよりも悪いです(はるかに悪いです!)。チェーンには、reinterpret_castと同じ効果、同じ問題がありますが、grepで簡単に見つけられるという利点はありません。
補遺
このように見てください。ケース1、reinterpret_castを使用し、すべてのプロジェクトフープを実行してその使用を正当化し、プロジェクトマネージャーが免除を許可します。数か月後、dynamic_castの使用にエラーが追跡されます。あなたは脱獄の無料カードを持っています。あなたにそのカードを与えるためにライン上にあるのはプロジェクトマネージャーのお尻です。
ケース2では、静的キャストの卑劣で手に負えないチェーンを使用し、コードは無傷でピアレビューを介して潜入します。数か月後、卑劣なテクニックの使用にエラーが追跡されます。あなたのプロジェクトマネージャーは、この厄介さを捕まえられないことで少し困っているかもしれませんが、それはあなたのお尻です。ジェイルフリーカードから抜け出すことはできません。あなたは囲碁を通過しません。あなたは直接失業ラインに行きます。
キャストの再解釈は常に最後の手段として使用してください。チェックは行われません。- したがって、操作に対して何らかの検証を行う 2 つ、3 つ、または 10 個のステートメントを連鎖させることができれば、価値のあるものを得ることができます。
シナリオのリストは非常に長くなる可能性があるため、簡単な言葉を入れています。
チェーンされたstatic_cast<>
s がコンパイルエラーを出さない場合は、避けるべきreinterpret_cast<>
です。
クロスキャスト ポインターの場合は使用しないreinterpret_cast
でください。代わりにvoid*
、への暗黙的な変換を使用してstatic_cast
ください。
理論的には、彼らは何か違うことをすることができるからです (そのようなケースを想像するのは難しいですが)。さらに重要なことに、それらは異なるシグナルをリーダーに送信し、コンパイラーに異なるストーリーを伝えます (これは最適化に影響を与える可能性があります)。論理的には、文字型への/からのケース (生メモリのイメージのダンプなど) や、明確に定義されて移植可能なその他のケース、および実際の低レベルのハードウェア依存を実行している場合は、チェーンstatic_cast
を使用することをお勧めします。作業: たとえば、アドレスを an にキャストしてa の指数フィールドを抽出し、ビット マスキングを行います。void*
reinterpret_cast
float
unsigned int*