我被告知句柄是一种指针,但不是,并且它允许您保持对对象的引用,而不是对象本身。什么是更精细的解释?
答案 0 :(得分:89)
句柄可以是从整数索引到指向内核空间中资源的指针。这个想法是它们提供了资源的抽象,所以你不需要了解资源本身就可以使用它。
例如,Win32 API中的HWND是Window的句柄。它本身就没用了:你无法收集它的任何信息。但是将它传递给正确的API函数,你可以用它执行大量不同的技巧。在内部,您可以将HWND视为GUI窗口表的索引(可能不一定是它的实现方式,但它使魔法变得有意义。)
编辑:不是100%肯定你在问题中具体提到的内容。这主要是谈论纯C / C ++。
答案 1 :(得分:43)
句柄是一个没有可见类型的指针或索引。通常你会看到类似的东西:
typedef void* HANDLE;
HANDLE myHandleToSomething = CreateSomething();
因此,在您的代码中,您只需将HANDLE作为不透明值传递。
在使用该对象的代码中,它将指针强制转换为实际结构类型并使用它:
int doSomething(HANDLE s, int a, int b) {
Something* something = reinterpret_cast<Something*>(s);
return something->doit(a, b);
}
或者它将它用作数组/向量的索引:
int doSomething(HANDLE s, int a, int b) {
int index = (int)s;
try {
Something& something = vecSomething[index];
return something.doit(a, b);
} catch (boundscheck& e) {
throw SomethingException(INVALID_HANDLE);
}
}
答案 2 :(得分:26)
句柄是一种指针,因为它通常是一种引用某个实体的方式。
更准确地说,指针是一种句柄,但并非所有句柄都是指针。
例如,句柄也可能是内存表中的一些索引,它对应于一个本身包含指向某个对象的指针的条目。
关键是当你有一个“句柄”时,你既不知道也不关心这个句柄最终如何识别它识别的东西,你需要知道的就是它。
显而易见的是,对于“究竟是什么样的句柄”没有单一的答案,因为即使在同一系统中,对不同事物的处理也可以在“引擎盖下”以不同的方式实现。但你不应该担心这些差异。
答案 3 :(得分:5)
在C ++ / CLI中,句柄是指向位于GC堆上的对象的指针。使用new
在(非托管)C ++堆上创建对象,new
表达式的结果是“普通”指针。使用gcnew
表达式在GC(托管)堆上分配托管对象。结果将是一个句柄。你不能在句柄上做指针运算。你没有释放句柄。 GC会照顾他们。此外,GC可以自由地重新定位托管堆上的对象,并在程序运行时更新句柄以指向新位置。
答案 4 :(得分:5)
这出现在Handle-Body-Idiom的上下文中,也称为Pimpl习语。它允许通过将实际数据保存到另一个类对象中来保持库的ABI(二进制接口)相同,该对象仅由“句柄”对象中保存的指针引用,该指针由委托给该类的函数组成。身体”。
启用两个对象的常量时间和异常安全交换也很有用。为此,只需要交换指向body对象的指针。
答案 5 :(得分:1)
HANDLE hnd;
与void * ptr;
HANDLE是Visual Studio(Windows)中winnt.h文件中定义的typedef:
typedef void *HANDLE;
详细了解HANDLE
答案 6 :(得分:1)
句柄是你想要的任何东西。
句柄可以是某些查找表中使用的无符号整数。
句柄可以是指向更大数据集的指针。
这取决于使用句柄的代码的行为方式。这决定了句柄类型。
使用术语“句柄”的原因很重要。这表明它们是对象的标识或访问类型。这意味着,对于程序员来说,它们代表了对某些内容的“关键”或访问权限。
答案 7 :(得分:0)
指针是句柄的一个特例。指针的好处是它直接在内存中标识一个对象,代价是对象变得不可重定位。句柄抽象出内存中对象的位置,但需要额外的上下文来访问它。例如,将句柄定义为数组索引,我们需要一个数组基指针来计算项目的地址。有时上下文在调用站点是隐含的,例如当对象池是全局的。这允许优化手柄的大小和使用,例如16 位 int 而不是 64 位指针。