13

私は C++ のバックグラウンドが強いとは言えません。そのため、Handle を最近頻繁に耳にします。Pointer とは何か (参照のようなメモリ位置のアドレスを格納する) は知っていますが、Handle とは何か、これら 2 つの違いは何かはよくわかりません。また、C# のサンプル コードを提供していただけると助かります。

ちなみに、私はこの用語をグーグルで検索しましたが、多くの人が異なる説明をしたので、SOから最高のものを得たと思います.

編集:

他の訪問者への簡単な警告:ハンドルは、リソースを指す参照のようなものです。Pointer のようにメモリ アドレスを指すことができますが、Handle はより一般的な用語であるため、疑似ポインタに似ています。ファイルはこれの良い例です。ファイルには、OS が認識してファイルを見つけるために使用できる ID を付けることができます。そのため、Handle はこの ID (メモリ アドレスである場合とそうでない場合があります) を保持でき、このハンドルを渡すと、OS はファイルを簡単に見つけることができます。

詳細については、以下の回答を参照してください。

編集:

この質問に対するすべての回答は素晴らしく、非常に説明的です。それらのいずれかを選択して回答としてマークするのに苦労しています。

4

3 に答える 3

14

申し訳ありませんが、C# の例はありませんが、次のようになります。

ポインタはメモリアドレスであり、この場合、オブジェクトがメモリに格納されている場所を指します。これは、C++ が C から継承した低レベルの概念です。

ハンドルについて:

ハンドルという用語は、別のオブジェクトに到達できるようにするあらゆる手法 (一般化された疑似ポインター) を意味するために使用されます。この用語は (意図的に) あいまいで曖昧です。

密接に関連するもう 1 つの重要な用語は、オブジェクトの「エイリアス」であるオブジェクト参照です。

このページでは、かなり明確で簡潔な回答が得られる場合があります

于 2012-05-22T14:32:28.457 に答える
6

HBITMAPハンドルは、操作socketによって影響を受けるオブジェクトを識別するために使用される抽象オブジェクト (ビットマップ、ソケット、ファイル、メモリなど) の識別子ですFILE*。オペレーティング システムのテーブルまたはマップのインデックス。

厳密に言えば、ポインタはメモリ内の正確な位置です。ポインターがハンドルとして使用されることもありますが、その逆が真になることはめったにありません。

オブジェクト指向環境では、ハンドルは低レベルのエンティティと見なされ、割り当てられたハンドルを使用して操作を呼び出すメソッドを持つオブジェクトでハンドルをオブジェクトにラップすることをお勧めします。その場合、ハンドルを保持するオブジェクトへの参照があります。たとえばCBitmapSystem.Net.Sockets.Socketstd::fstream、 などです。

言語の宗教戦争を掘り下げることなく、どちらか一方がよりクリーンで、より安全で、より速く、より簡単であると主張する人もいます。ほとんどの場合、使用している環境によって異なります。選択肢がある場合は、C# でハンドルを直接使用することはお勧めしませんが、C ではハンドルを使用する方がはるかに簡単 (かつ必要) です。

重要な注意: .Net 環境では、マーシャリングを行う必要がある場合、ハンドルと呼ばれる実際のオブジェクト参照について何かを読むことになります。これは、それらが実際にはポインターではなく内部のハンドルであるためです。したがって、オブジェクトのメソッドを呼び出すと、コンパイラは実際には、メモリ内を自由に移動できるオブジェクトへのハンドルを使用してメソッドを呼び出しています。これにより、ガベージ コレクタがメモリの断片化を回避できるようになります。したがって、 を使用System.Drawing.Bitmapすると、Handle to a Pointer to a Handle になります。

編集:

例、C++ の stdio/fstream:

// Read a short line from a file and output it to the console
// 256 bytes max for simplicity purposes

char buffer[256];

// With handle
FILE* file = fopen ("file.txt" , "r");
fgets(buffer, 256 , file);
std::cout << buffer << std::endl;
fclose (file);

// With object reference
{
  std::ifstream stream ("file.txt");
  stream.getline(buffer, 256);
  std::cout << buffer << std::endl;
}

一番上の例では、ファイルへのハンドルと見なされるものを使用しFILE*ています。fileハンドルは を使用して割り当てられ、やなどのfopen操作に渡されます。ハンドルの割り当てを解除します。fgets()close()close()

一番下の例は を使用していstd::ifstreamます。ハンドルはオブジェクト コンストラクターで割り当てられ、そのオブジェクトの内部にあります。ファイルに対して操作を行うには、そのオブジェクトによって提供される などのメソッドを使用しますgetline()。オブジェクトがスコープ外になると、つまり閉じ括弧でハンドルがストリーム デストラクタによって割り当て解除されます。または、オブジェクトがヒープに割り当てられている場合は、明示的に削除する必要があります。

于 2012-05-22T15:11:46.470 に答える
5

ハンドルは、リソースの代役として機能する単なる情報の一部です。

最も一般的な例はファイル ハンドルです。これは多くの場合、開いた各ファイルを区別できるように割り当てられた整数にすぎません。これらは、すべてのファイルが含まれる C などの言語でより頻繁に使用されます。 open()は整数を返し、他のすべてのファイル アクセス関数では、意味するファイルを指定するために、その値を引数として渡す必要があります。たとえば、関数int read(int fd, void * ptr, int numbytes)では、これを の引数として渡しますfd

C には、おなじみの 3 つの標準ファイル ハンドルが用意されています。

  • 0: 標準入力
  • 1: 標準出力
  • 2: 標準誤差

C# では、通常、ハンドルは実装の詳細として抽象化され、代わりに対話するオブジェクトが与えられます。私がすぐに思いつく最も良い例は、(現在非推奨になっている) FileStream.Handleプロパティです。

public virtual IntPtr Handle { get; }
于 2012-05-22T14:45:24.560 に答える