我不能说我有很强的C ++背景,所以这些天我经常听到Handle。我知道Pointer是什么(它存储内存位置的地址就像参考)但我不确定Handle是什么以及这两者之间的区别。如果你能提供一个C#中的示例代码就会很棒。
顺便说一下,我用Google搜索了这个术语,然而很多人给出了不同的解释,所以我觉得我从SO中得到了最好的解释。
修改
为其他访问者快速提醒:句柄就像是指向资源的参考。它可以指向像指针一样的内存地址,但Handle是更通用的术语,所以它更像是一个伪指针。文件就是一个很好的例子。文件可以具有操作系统可以理解并用于查找文件的ID。因此Handle可以保存此ID(可能是也可能不是内存地址),当我们通过此Handle时,操作系统可以轻松找到该文件。
请参阅以下答案以获取更多详细信息。
修改
这个问题下的所有答案都很棒且很有说服力。我很难选择其中一个来标记答案。
答案 0 :(得分:9)
抱歉,没有C#示例,但是:
指针是一个内存地址,在这种情况下指向对象存储在内存中的位置。这是C ++从C继承的低级概念。
关于句柄:
术语句柄用于表示允许您到达另一个对象的任何技术 - 通用伪指针。该术语(故意)含糊不清,含糊不清。
与密切相关的一个更重要的术语是对象引用,它是对象的“别名”。
您可以在this page
上获得相当简洁明了的答案答案 1 :(得分:5)
句柄是抽象对象(位图,套接字,文件,内存等等)的标识符,用于标识哪个对象受操作影响:HBITMAP
,socket
,{ {1}}是句柄的示例 - 它们实际上是整数,可能表示操作系统中某些表或映射中的索引。
严格地说,指针是内存中的精确位置。虽然指针有时被用作句柄,但反转很少(如果有的话)为真。
在面向对象的环境中,句柄被视为低级实体,将对象包装在对象中是一种很好的做法,对象具有使用已分配句柄调用操作的方法。在这种情况下,您可以引用一个持有句柄的对象,例如:FILE*
,CBitmap
,System.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
分配,并传递给fopen
和fgets()
等操作。 close()
解除分配句柄。
底部示例使用close()
。句柄在对象构造函数中分配,并且是该对象的内部。要对文件进行操作,请使用该对象提供的方法,例如std::ifstream
。当对象超出范围时,即在结束括号时,流析构函数释放句柄,或者如果对象是在堆上分配的,则需要明确地删除它。
答案 2 :(得分:4)
句柄只是一条信息,可作为资源的替身。
最常见的示例是文件句柄,它通常只是一个分配给您打开的每个文件的整数,以便您可以区分它们。它们在C语言中经常使用,其中包含所有文件。 open()
返回一个整数,然后在所有其他文件访问函数中,您需要将该值作为参数传递,以指定您所指的文件。例如,在函数int read(int fd, void * ptr, int numbytes)
中,您可以将其作为fd
的参数传递。
C提供3个标准文件句柄,听起来很熟悉:
在C#中,句柄通常被抽象为实现细节,而是给你一个与之交互的对象。我能想到的一个最好的例子是(现已弃用)FileStream.Handle属性:
public virtual IntPtr Handle { get; }