との両方がstatic_cast
、別のポインター型へのreinterpret_cast
キャストに対して正常に機能するようです。void*
どちらか一方を優先する正当な理由はありますか?
8 に答える
使用static_cast
: ここで行われる変換を正確に記述するのは、最も狭いキャストです。
reinterpret_cast
「タイプ セーフを完全に無視し、A から B にキャストする」ことを意味するため、using の方が適しているという誤解があります。
ただし、これは実際には の効果を説明しているわけではありませんreinterpret_cast
。むしろ、reinterpret_cast
いくつかの意味がありますが、そのすべてについて、「によって実行されるマッピングreinterpret_cast
は実装定義である」と言えます。[5.2.10.3]
しかし、マッピングからvoid*
へのキャストの特定のケースでは、標準によって完全に明確に定義されています。T*
つまり、アドレスを変更せずに型のないポインターに型を割り当てることです。
これが好まれる理由static_cast
です。
さらに、間違いなくもっと重要なことは、 のすべての使用reinterpret_cast
は実に危険であるという事実です。これは、実際には (ポインターの場合) 何かを他のものに変換するためstatic_cast
です。これにより、誤ってあるポインター型を別の型に強制しようとしたバグから既に救われました。
は、 aを他の型のポインタにstatic_cast
変換するのにより適しています。void*
static_cast
実行時に動作することが必ずしも保証されていない 2 つの型の間の自然で直感的な変換がある場合に選択するキャストです。たとえば、 を使用static_cast
して、基底クラス ポインターを派生クラス ポインターに変換できます。これは、場合によっては意味のある変換ですが、実行時まで検証できません。同様に、 を使用して から に変換できます。static_cast
これは明確に定義されていますが、実行時に精度が失われる可能性があります。int
char
reinterpret_cast
一方、は、基本的に安全ではない、または移植性がない変換を行うように設計されたキャスト演算子です。たとえば、 を使用して aから anreinterpret_cast
に変換できます。これは、システムに≤がある場合に正しく機能します。を使用して aを an に、またはその逆に変換することもできます。これは、プラットフォーム固有のものです。これは、 s とs の特定の表現が互いに共通点を持つことが保証されていないためです。void *
int
sizeof (void*)
sizeof (int)
reinterpret_cast
float*
int*
float
int
要するに、キャストが論理的に意味があるが、実行時に必ずしも成功するとは限らない変換を行っていることに気付いた場合は、reinterpret_cast
. static_cast
実行時にキャストが機能することを事前に知っていて、コンパイラに「これが機能しない可能性があることはわかっていますが、少なくとも理にかなっており、正しく機能すると信じる理由があります。実行時に正しいことを行います。」コンパイラは、キャストが関連する型間であることを確認し、そうでない場合はコンパイル時エラーを報告します。ポインター変換でこれを行うために使用reinterpret_cast
すると、コンパイル時の安全性チェックが完全にバイパスされます。
dynamic_cast
の代わりに aを使用したい状況がいくつかありますがstatic_cast
、これらのほとんどはクラス階層でのキャストを含み、(ごくまれに) に直接関係しvoid*
ます。
仕様でどちらが優先されるかについては、どちらも「使用するのに適したもの」として過度に言及されていません (または、少なくとも、このように言及されているものを覚えていません)。ただし、仕様では、使いstatic_cast
すぎreinterpret_cast
。たとえば、次のように C スタイルのキャストを使用する場合
A* ptr = (A*) myVoidPointer;
static_cast
試行されたキャスト演算子の順序は、常に a の前に aを使用しようとします。これは、移植性が保証されていないreinterpret_cast
ため、必要な動作です。reinterpret_cast
これは難しい質問です。一方で、Konrad は reinterpret_cast の仕様定義について優れた点を指摘していますが、実際にはおそらく同じことを行います。一方、ポインター型間でキャストしている場合 (たとえば、char* を介してメモリ内でインデックスを作成する場合はかなり一般的です)、static_castはコンパイラ エラーを生成し、とにかく reinterpret_cast を使用することを余儀なくされます。
実際には、キャスト操作の意図をより説明するため、reinterpret_castを使用します。確かに、別の演算子がポインターの再解釈のみを指定するケースを作成できますが (これにより、同じアドレスが返されることが保証されます)、標準にはありません。
暗黙の変換でそれを取得した可能性が高いので、暗黙の変換に最も近いのでvoid*
使用する必要があります。static_cast
これに使用static_cast
します。他に使用する方法がない場合にのみ、最もまれなケースでのみ使用しますreinterpret_cast
。
常に可能な限り弱いキャストを使用することをお勧めします。
reinterpret_cast
へのポインターをキャストするために使用できますfloat
。キャストが構造を壊すほど、使用には注意が必要です。
の場合、char*
いくつかの が得られるまで、c スタイルのキャストを使用しますreinterpret_pointer_cast
。
reinterpret_cast
void*
をターゲットデータ型に強制的に変換します。安全性を保証するものではなく、基になるオブジェクトが何かである可能性があるため、プログラムがクラッシュする可能性があります。
たとえば、myclass*
toを型キャストしてから、完全に異なるレイアウトを持つ可能性のあるに変換するためにvoid*
使用できます。reinterpret_cast
yourclass*
したがって、使用することをお勧めしますstatic_cast