指针和句柄之间有什么区别

Tar*_*rik 9 .net clr pointers handle

我不能说我有强大的C++背景,所以这些天我经常听到Handle.我知道Pointer是什么(它存储内存位置的地址就像参考),但我不确定Handle是什么以及这两者之间的区别.如果你能提供一个C#中的示例代码就会很棒.

顺便说一下,我用Google搜索了这个术语,然而很多人给出了不同的解释,所以我觉得我从SO中得到了最好的解释.

编辑:

为其他访客快速提醒:句柄就像是指向资源的参考.它可以指向像指针一样的内存地址,但Handle是更通用的术语,所以它更像是一个伪指针.文件就是一个很好的例子.文件可以具有操作系统可以理解并用于查找文件的ID.因此Handle可以保存此ID(可能是也可能不是内存地址),当我们通过此Handle时,OS可以轻松找到该文件.

有关更多详细信息,请参阅以下答案.

编辑:

这个问题下的所有答案都很棒,很有说服力.我很难选择其中一个来标记它作为答案.

Ale*_*mer 9

对不起,没有C#示例,但是:

指针是一个内存地址,在这种情况下指向对象存储在内存中的位置.这是C++从C继承的低级概念.

关于手柄:

术语句柄用于表示允许您到达另一个对象的任何技术 - 通用伪指针.该术语(故意)含糊不清,含糊不清.

与之密切相关的一个更重要的术语是对象引用,它是对象的"别名".

您可以在此页面上获得相当清晰简洁的答案


Sea*_*n U 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; }
Run Code Online (Sandbox Code Playgroud)


Coi*_*oin 5

手柄是一个标识符,以用于鉴定目的通过一种操作的影响的抽象对象(位图,插座,文件,存储器,等等): ,,HBITMAP 是例如把手的-它们实际上是整数可能代表一个操作系统中某些表或映射中的索引.socketFILE*

严格来说,指针是内存中的精确位置.虽然指针有时用作句柄,但反转很少(如果有的话)为真.

在面向对象的环境中,句柄被认为是低级实体,将对象包装在对象中是一种很好的做法,对象具有使用分配的句柄调用操作的方法.在这种情况下,你必须持有句柄对象的引用,比如:CBitmap,System.Net.Sockets.Socket,std::fstream等.

如果不钻研语言宗教战争,有些人会争辩说,其中一种更干净,更安全,更快捷,更容易.它几乎总是取决于你所处的环境 - 如果你有选择的话,你不建议直接在C#中使用句柄,而在C中,使用句柄会更简单(和必要).

重要说明:在.Net环境中,如果您必须进行编组,最终将阅读有关被称为句柄的实际对象引用的内容.这是因为它们实际上是在引擎盖下处理而不是指针.因此,当您在对象上调用方法时,编译器实际上是使用句柄来调用该方法,该句柄可以在内存中自由移动.这使得垃圾收集器可以避免内存碎片.因此,System.Drawing.Bitmap最终得到一个指针到句柄的句柄.

编辑:

例如,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;
}
Run Code Online (Sandbox Code Playgroud)

顶部示例使用应被视为FILE*文件句柄的内容.该file手柄使用分配fopen并传递到操作,如fgets()close().close()解除分配手柄.

底部示例使用std::ifstream.句柄在对象构造函数中分配,并且是该对象的内部.要对文件进行操作,请使用该对象提供的方法,例如getline().当对象超出范围时,即在结束括号时,流析构函数释放句柄,或者如果在堆上分配了对象,则需要明确地删除它.