C ++のハンドルとは何ですか?


97

ハンドルは一種のポインタであるが、そうではなく、オブジェクト自体ではなくオブジェクトへの参照を維持できると言われました。より複雑な説明とは何ですか?



2
Chain of Responsibilityパターンを調べると、「ハンドル」は基本的にノードであり、「ハンドラ」はそれらの小さなセットであることがわかります。「魔法」は再帰から来ています

回答:


100

ハンドルは、整数インデックスからカーネルスペース内のリソースへのポインターまで何でもかまいません。アイデアは、それらがリソースの抽象化を提供するので、それを使用するためにリソース自体について多くを知る必要はないということです。

たとえば、Win32 APIのHWNDはウィンドウのハンドルです。それ自体では役に立たないので、そこから情報を収集することはできません。しかし、それを適切なAPI関数に渡すと、それを使用してさまざまなトリックを実行できます。内部的には、HWNDをGUIのウィンドウのテーブルへの単なるインデックスと考えることができます(これは必ずしも実装方法とは限りませんが、それは魔法の理にかなっています)。

編集:あなたが質問で具体的に何を求めていたのか100%確実ではありません。これは主に純粋なC / C ++について話しています。


13
ハンドルは、(とりわけ)状態を保存するのに役立ちます。uがstd :: vectorのような構造のデータを持っている場合。オブジェクトは、プログラムの実行中のさまざまな時点でさまざまなメモリ位置にある可能性があります。つまり、そのメモリへのポインタは値を変更します。ハンドルがあるため、変更されることはなく、常にオブジェクトを参照します。(ゲームのように)プログラムの状態を保存することを想像してみてください-ポインターの位置をデータに保存し、後でそのデータを再度インポートして、そのアドレスをメモリに取得しようとはしません。ただし、データとともにハンドルを保存し、データとハンドルをインポートすることができます。
SinisterRainbow 2012

Linuxでハンドルを同等のものに変換することは可能ですか?HANDLEを使用するプログラムをWindowsからLinuxに移行する必要があります。
Cornel Verster、2015年

1
それが正解です。それらは何でもかまいません。また、それらを使用するコードがハンドルのタイプを定義します。私は後世のために、私自身の同様の答えのより簡潔なバージョンを作ろうとしましたが、自分自身を助けることができませんでした。@CornelVerster-Linuxでも同じです。つまり、OSハンドルではなく、概念です。そのため、移行に関するハンドル、または移行する必要があるかどうかに依存します。
ダイアスタ2017

@Matthew Iselin:APIドキュメントで、ハンドラーであると定義している場合は、それらを関数に渡す必要があります。そうでない場合、APIドキュメントでハンドラーが何であるかを知る方法
Amin Khormaei

51

ハンドルは、可視の型が関連付けられていないポインターまたはインデックスです。通常、次のようなものが表示されます。

 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);
     }
 }

29

ハンドル、ある種のエンティティを参照する方法であるという点で一種のポインタです。

ポインタはハンドルの1つのタイプであると言う方がより正確ですが、すべてのハンドルがポインタであるとは限りません。

たとえば、ハンドルは、メモリ内テーブルへのインデックスでもあります。これは、それ自体が何らかのオブジェクトへのポインタを含むエントリに対応しています。

重要なことは、「ハンドル」を持っている場合、そのハンドルが実際にそれが識別するものをどのようにして識別してしまうのかを知らず、気にもしないということです。

同じシステムであっても、異なるものへのハンドルは「内部」で異なる方法で実装される可能性があるため、「ハンドルとは何か」に対する単一の回答がないことも明らかです。しかし、それらの違いを気にする必要はありません。


6

C ++ / CLIでは、ハンドルはGCヒープにあるオブジェクトへのポインターです。(アンマネージ)C ++ヒープ上にオブジェクトを作成するには、を使用newnewます。式の結果は「通常の」ポインターです。管理対象オブジェクトは、gcnew式を使用してGC(管理対象)ヒープに割り当てられます。結果はハンドルになります。ハンドルに対してポインター演算を行うことはできません。ハンドルを解放しません。GCがそれらを処理します。また、GCは、プログラムの実行中に、マネージヒープ上のオブジェクトを自由に再配置し、新しい場所を指すようにハンドルを更新できます。


5

これは、Pimpl イディオムとも呼ばれるHandle-Body-Idiomのコンテキストで表示されます。これにより、実際のデータを別のクラスオブジェクトに保持することにより、ライブラリのABI(バイナリインターフェイス)を同じに保つことができます。これは、「ハンドル」オブジェクトに保持されたポインタによって参照されるだけであり、そのクラスにデリゲートする関数で構成されます体"。

また、2つのオブジェクトの一定時間および例外セーフスワップを有効にすることも役立ちます。このためには、ボディオブジェクトを指すポインタを交換するだけです。


2

ハンドルとは、あなたが望むものです。

ハンドルは、一部のルックアップテーブルで使用される符号なし整数にすることができます。

ハンドルは、より大きなデータセットへのポインタ、またはデータセットへのポインタにすることができます。

ハンドルを使用するコードの動作に依存します。これにより、ハンドルのタイプが決まります。

ハンドル」という用語が使用される理由は重要です。これは、オブジェクトの識別またはアクセスタイプとしてそれらを示します。つまり、プログラマにとって、それらは「キー」または何かへのアクセスを表します。


2

HANDLE hnd; と同じです void * ptr;

HANDLEは、Visual Studio(Windows)のwinnt.hファイルで定義されたtypedefです。

typedef void *HANDLE;

HANDLEについてもっと読む


1
これはWindowsにのみ適用され、Windowsアーキテクチャで使用される多くの種類のハンドルのうちの1つだけです。ただし、これ「通常のWindowsアプリケーションレベルのハンドル」と呼ばれます。
ダイアスタ2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.