C++:整数をポインタにキャストする安全な方法
-
11-09-2019 - |
質問
アドレスを含む整数型を実際のポインタ型に変換する必要があります。次のように reinterpret_cast を使用できます。
MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);
ただし、問題のアドレスが実際に MyClass オブジェクトを保持しているかどうかを確認するための実行時チェックは実行されません。最初に void* に変換し (reinterpret_cast を使用)、次にその結果に対してdynamic_cast を使用することに利点があるかどうかを知りたいです。このような:
void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);
2 番目の方法を使用することに利点はありますか?
解決
別のC ++インプリメンテーションによって異なる方法で実装されているdynamic_cast
に型チェック。あなたが特定の実装のための答えをしたい場合は、あなたが使用しているものを実装言及する必要があります。一般的に質問に答えるための唯一の方法は、ISO標準C ++を参照することです。
標準の私の読書することにより、ボイドポインタのdynamic_cast
を呼び出すことは違法です。
dynamic_cast<T>(v)
「Tがポインタ型である場合は、Vクラスタイプを完了するために、ポインタの右辺値でなければならない」
(ISO C ++標準の5.2.7.2から)。 void
は、完全なクラス型ではないので、式は違法です。
興味深いことに、タイプがキャストされているからのボイドポインタ、すなわちであることが許可されます。
void * foo = dynamic_cast<void *>(some_pointer);
この場合、dynamic_cast
は常に成功し、得られた値は、最も派生オブジェクトへのポインタではv
によって指されます。
他のヒント
いいえ、特定の利点は、そうではありません。あなたがreinterpret_cast
を使用した瞬間は、すべてのベットはオフになっています。これは、キャストが有効であることを確認するためにあなた次第です。
実際には深刻な利点。もしあなたが未定義の動作に実行する多型オブジェクトへのポインタ(通常はアクセス違反)ではない何かにvoid *型のポイントすぐます。
安全な方法は、すべてのライブMyClassのオブジェクトの記録を維持することです。それはあなたが簡単に追加、削除、および要素をテストすることができることを意味、std::set<void*>
でこの記録を保存するのがベストです。
void*
sとしてそれらを格納するための理由は、あなたの整数から非整列MyClass*
ポインタを作成するようnastynessリスクはありませんということです。
まずは「再解釈」
int
にvoid *
それは悪い考えです。もしsizeof(int)
は 4 であり、sizeof(void *)
8 (64x システム) は不正な形式です。さらに
dynamic_cast
は多態性クラスの場合にのみ有効です。
オプション1はあなただけ(半)ポータブル/有効なオプションです。
オプション2:dynamic_castを有効なものとしてC ++(無効として許可されていません)ではありません。
。は、実装レベルでは、それは、先の型に到達するためにソース・タイプからの情報を入力する必要があります。そう、これはどちらか有効ではありません空からのランタイムのソースタイプの情報を取得する方法(または方法はありません)*はありません。
のdynamic_castをアップCASと未知のタイプのない型階層ダウンするために使用されます。
側としては、おそらく型なしポインタを格納するためにvoid *型ではなく整数を使用する必要があります注意してください。 intはないポインタを格納するのに十分な大きさであるために可能性があります。
C++ でポインターを処理する最も安全な方法は、ポインターをタイプセーフに処理することです。これはつまり:
- ポインタをポインタ以外のものに格納しないでください
- void ポインタを避ける
- 他のプロセスにポインタを渡さないでください
- スレッド上でポインタを使用する予定がある場合は、weak_ptr を検討してください。
その理由は次のとおりです。あなたが行おうとしていることは安全ではなく、安全でない (レガシー?) コードとやり取りしない限り、回避することができます。この場合、MSalters の答えを検討してください。ただし、それでも面倒であることに注意してください。
あなたが知られている基本クラスにthe_integer
ポイント(つまり、少なくとも1人の仮想メンバーを持っている)、実際には利点があるかもしれないことを確かに知っている場合:オブジェクトは、特定の派生クラスであることを知っています。しかし、あなたは最初にあなたのベースクラスにreinterpret_cast
、その後dynamic_cast
をしなければならないと思います:
BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);
void*
でdynamic_cast
を使用することは役に立たないし、単に間違っています。有効なオブジェクトがメモリ内のいくつかの任意の位置があるかどうかを確認するためにdynamic_cast
を使用することはできません。
また、注意を払う必要があります。アーキテクチャはsizeof(void *型)!=はsizeof(int型)、例えばがあります。 LP64ます。