13

我不能说我有很强的 C++ 背景,所以这些天我经常听到 Handle。我知道指针是什么(它存储内存位置的地址,如引用),但我不确定句柄是什么以及这两者之间的区别是什么。如果你能提供一个 C# 中的示例代码,那就太好了。

顺便说一句,我用谷歌搜索了这个术语,但是很多人给出了不同的解释,所以我认为我从 SO 中得到了最好的解释。

编辑:

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

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

编辑:

这个问题下的所有答案都很棒而且非常解释。我很难选择其中一个来将其标记为答案。

4

3 回答 3

14

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

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

关于手柄:

句柄一词用于表示任何可以让您访问另一个对象的技术——通用伪指针。该术语(故意)含糊不清。

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

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

于 2012-05-22T14:32:28.457 回答
6

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

严格来说,指针是内存中的一个精确位置。虽然指针有时用作句柄,但很少(如果有的话)反之亦然。

在面向对象的环境中,句柄被认为是低级实体,最好将句柄包装在对象中,该对象具有使用分配的句柄调用操作的方法。在这种情况下,您有一个对持有句柄的对象的引用,例如:CBitmapSystem.Net.Sockets.Socketstd::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;
}

上面的例子使用了应该被认为是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 回答