web-dev-qa-db-ja.com

void *を何にキャストするときにstatic_castまたはreinterpret_castを使用する必要がありますか

Static_castとreinterpret_castは両方とも、void *を別のポインター型にキャストする場合に正常に機能するようです。一方を他方よりも優先する正当な理由はありますか?

175
Andy

static_castを使用:ここで行われる変換を正確に記述する最も狭いキャストです。

reinterpret_castを使用すると、「型の安全性を完全に無視し、AからBにキャストするだけ」という意味になるため、より良い一致であるという誤解があります。

ただし、これは実際にはreinterpret_castの効果を説明するものではありません。むしろ、reinterpret_castには多くの意味があり、そのすべてにおいて、「reinterpret_castによって実行されるマッピングは実装定義です」[5.2.10.3]

しかし、void*からT*へのキャストの特定の場合、マッピングは標準によって完全に明確に定義されています。つまり、アドレスを変更せずに型を型なしポインターに割り当てることです。

これがstatic_castを好む理由です。

さらに、おそらく間違いなくより重要なことは、reinterpret_castの使用はすべて(ポインターの場合)実際に何かに変換されるため、まったく危険であるという事実です。一方、static_castの方がはるかに制限されているため、保護レベルが向上します。これにより、あるポインタータイプを誤って別のポインタータイプに強制しようとするバグをすでに回避できました。

125
Konrad Rudolph

これは難しい質問です。一方で、Konradはreinterpret_castの仕様定義について優れた点を挙げていますが、実際にはおそらく同じことをしているでしょう。一方、ポインタ型間でキャストしている場合(たとえば、char *を介してメモリ内でインデックスを作成する場合によくあるように)、static_castはコンパイラエラーを生成し、強制的に実行されますとにかくreinterpret_castを使用します。

実際には、reinterpret_castを使用します。これは、キャスト操作の意図をより詳細に説明するためです。確かに、異なる演算子がポインターの再解釈のみを指定するように主張することもできます(これは同じアドレスが返されることを保証します)が、標準にはありません。

7
Nick

可能な限り弱いキャストを常に使用することをお勧めします。

reinterpret_castを使用して、ポインターをfloatにキャストできます。キャストが構造を破壊するほど、それを使用する注意が必要になります。

char*の場合は、reinterpret_pointer_castが得られるまでCスタイルのキャストを使用します。これはより弱く、他に十分なものがないためです。

0