ハンドルは一種のポインターですが、そうではなく、オブジェクト自体ではなくオブジェクトへの参照を保持できると言われました。より詳細な説明は何ですか?
8 に答える
ハンドルは、整数インデックスからカーネル空間内のリソースへのポインターまで、何でもかまいません。アイデアは、リソースの抽象化を提供するため、リソースを使用するためにリソース自体について多くを知る必要はありません。
たとえば、Win32 API の HWND はウィンドウのハンドルです。それ自体は役に立ちません。そこから情報を収集することはできません。しかし、それを適切な API 関数に渡せば、それを使ってさまざまなトリックを実行できます。内部的には、HWND は、GUI のウィンドウ テーブルへの単なるインデックスと考えることができます (実装方法は必ずしもそうではないかもしれませんが、魔法の意味は理解できます)。
編集:質問で具体的に何を求めていたのか、100%確実ではありません。これは主に純粋な C/C++ について話しています。
ハンドルは、目に見える型がアタッチされていないポインターまたはインデックスです。通常、次のようなものが表示されます。
typedef void* HANDLE;
HANDLE myHandleToSomething = CreateSomething();
したがって、コードでは、不透明な値として HANDLE を渡すだけです。
オブジェクトを使用するコードでは、ポインターを実際の構造体型にキャストして使用します。
int doSomething(HANDLE s, int a, int b) {
Something* something = reinterpret_cast<Something*>(s);
return something->doit(a, b);
}
または、配列/ベクトルへのインデックスとして使用します。
int doSomething(HANDLE s, int a, int b) {
int index = (int)s;
try {
Something& something = vecSomething[index];
return something.doit(a, b);
} catch (boundscheck& e) {
throw SomethingException(INVALID_HANDLE);
}
}
ハンドルは、通常、何らかのエンティティを参照する方法であるという点で、一種のポインターです。
ポインターはハンドルの 1 つのタイプであると言ったほうが正確ですが、すべてのハンドルがポインターであるとは限りません。
たとえば、ハンドルは、オブジェクトへのポインターを含むエントリに対応する、メモリ内テーブルへのインデックスである場合もあります。
重要なことは、「ハンドル」がある場合、そのハンドルが実際に識別するものをどのように識別するかを知らないか気にしないということです。知っておく必要があるのは、それがそうするということだけです。
また、同じシステム内であっても、さまざまなものへのハンドルがさまざまな方法で「ボンネットの下」で実装される可能性があるため、「ハンドルとは何か」に対する単一の答えがないことも明らかです。しかし、これらの違いを気にする必要はありません。
C++/CLI では、ハンドルは GC ヒープにあるオブジェクトへのポインターです。(アンマネージ) C++ ヒープ上にオブジェクトを作成するにnew
は、式の結果がnew
「通常の」ポインターになります。マネージド オブジェクトは、gcnew
式を使用して GC (マネージド) ヒープに割り当てられます。結果はハンドルになります。ハンドルに対してポインター演算を行うことはできません。ハンドルを解放しません。GC がそれらを処理します。また、GC はマネージド ヒープ上のオブジェクトを自由に再配置し、プログラムの実行中に新しい場所を指すようにハンドルを更新できます。
これは、 Pimpl イディオムとも呼ばれるHandle-Body-Idiomのコンテキストで表示されます。実際のデータを別のクラス オブジェクトに保持することにより、ライブラリの ABI (バイナリ インターフェイス) を同じに保つことができます。このクラス オブジェクトは、そのクラスにデリゲートする関数で構成される「ハンドル」オブジェクトに保持されているポインタによって参照されるだけです。体"。
2 つのオブジェクトのコンスタント タイムおよび例外セーフ スワップを有効にすることも役立ちます。このためには、本体オブジェクトを指すポインタを交換するだけです。