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

时间:2012-05-22 14:23:47

标签: .net pointers clr handle

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

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

修改

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

请参阅以下答案以获取更多详细信息。

修改

这个问题下的所有答案都很棒且很有说服力。我很难选择其中一个来标记答案。

3 个答案:

答案 0 :(得分:9)

抱歉,没有C#示例,但是:

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

关于句柄:

  

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

与密切相关的一个更重要的术语是对象引用,它是对象的“别名”。

您可以在this page

上获得相当简洁明了的答案

答案 1 :(得分:5)

句柄是抽象对象(位图,套接字,文件,内存等等)的标识符,用于标识哪个对象受操作影响:HBITMAPsocket,{ {1}}是句柄的示例 - 它们实际上是整数,可能表示操作系统中某些表或映射中的索引。

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

在面向对象的环境中,句柄被视为低级实体,将对象包装在对象中是一种很好的做法,对象具有使用已分配句柄调用操作的方法。在这种情况下,您可以引用一个持有句柄的对象,例如:FILE*CBitmapSystem.Net.Sockets.Socket等。

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

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

修改

示例,C ++中的stdio / fstream:

System.Drawing.Bitmap

顶部示例使用应该被视为文件句柄// 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分配,并传递给fopenfgets()等操作。 close()解除分配句柄。

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

答案 2 :(得分:4)

句柄只是一条信息,可作为资源的替身。

最常见的示例是文件句柄,它通常只是一个分配给您打开的每个文件的整数,以便您可以区分它们。它们在C语言中经常使用,其中包含所有文件。 open()返回一个整数,然后在所有其他文件访问函数中,您需要将该值作为参数传递,以指定您所指的文件。例如,在函数int read(int fd, void * ptr, int numbytes)中,您可以将其作为fd的参数传递。

C提供3个标准文件句柄,听起来很熟悉:

  • 0:标准输入
  • 1:标准输出
  • 2:标准错误

在C#中,句柄通常被抽象为实现细节,而是给你一个与之交互的对象。我能想到的一个最好的例子是(现已弃用)FileStream.Handle属性:

public virtual IntPtr Handle { get; }