2017-06-30 4 views
23

私はstatic_castがあるタイプから別のタイプへのキャストであることを理解しています。(直観的に)ある状況下では成功する可能性があり、危険なキャストがなければ有意義なキャストです。一方、reinterpret_castは、ある値のビットを別の値のビットとして再解釈する危険な変換を表すキャストです。C++型キャスト。 static_castはいつ成功し、reinterpret_castは問題を引き起こしますか?

コードがコンパイル、キャストされ、static_castが問題を起こさないが、reinterpret_castで問題が発生する場合、誰かがシナリオを記述できますか?

+0

標準で明確な結果が得られていると明確に列挙されていないreinterpret_castは、問題を引き起こす可能性があり、少なくともプログラムを形式的に不正な形にする可能性があります。 –

+4

複数の継承を持つ基本クラスへのキャスト –

答えて

20

これはそれを行います。

#include <iostream> 
using namespace std; 

struct C{int n;}; 
struct A{int n;}; 
struct B : A, C{}; 

int main() 
{ 
    B b; 
    B* pb = &b; 
    cout << static_cast<C*>(pb) << "\n"; 
    cout << reinterpret_cast<C*>(pb); 
} 

二つのアドレスの違いに注意してください。

ここでは、いくつかの多重継承を構築し、空の基底クラスのサイズゼロへの最適化を回避するために、明示的なメンバーを基底クラスに入れました。

は、最も単純な、そのような場合は、非NULLポインタを生じ得るreinterpret_cast<void*>(NULL)、あるhttps://ideone.com/QLvBku

+4

注:多重継承を持たない基本クラスと仮想メソッドを持つ派生クラスは、 "v-ptr"サイズのオフセット(潜在的な埋め込み)を生成します。 –

9

このような場合の1つは、複数の継承です。つまり、キャスト後のベースオブジェクトポインタのアドレスは、派生オブジェクトアドレスと異なる可能性があり、正しいベースクラス項目を指すようになります。

reinterpret_castはアドレス調整を行わないため、キャストからベースへのクラスが間違ったアドレスを使用する可能性があります(つまり、常に派生オブジェクトのアドレスは変更されません)。

15

参照します。

対照的に、static_cast<void*>(NULL)はヌルポインタを生成する必要があるため安全です。

なぜですか? NULLは0に等しい整数定数です。static_castは、0を適切なヌルポインタに変換する必要がありますが、reinterpret_castには同じ要件がありません。ヌルポインタの内部表現が整数ゼロと同じでない場合、結果は異なります。このタイプの破損は、セグメンテーションされたアドレッシングを持つアーキテクチャで最もよく起こります。

+0

私はこれが驚くべきことだと思います。 'reinterpret_cast (NULL)'がnull以外を返すことがある理由とその理由をさらに拡張できますか? – Cornstalks

+2

'reinterpret_cast'のCPPリファレンスは" *ヌルポインタ定数 'NULL'または整数ゼロはターゲットタイプのヌルポインタ値を保証するものではなく、' static_cast'または暗黙の変換を使用してください* " –

+0

@TobySpeight:そして 'nullptr'の何?私はこれが修正されたことを願っています... –

関連する問題