C ++中的句柄是什么?


97

有人告诉我句柄是某种指针,但不是,它使您可以保留对对象的引用,而不是对象本身。什么是更详尽的解释?



2
查看责任链模式,您将了解“句柄”基本上是一个节点,而“处理程序”只是其中的一小部分。“魔术”来自递归

Answers:


100

句柄可以是任何值,从整数索引到内核空间中资源的指针。这个想法是,它们提供了资源的抽象,因此您无需了解有关资源本身的任何知识即可使用它。

例如,Win32 API中的HWND是Window的句柄。就其本身而言,它是无用的:您无法从中收集任何信息。但是将其传递给正确的API函数,您可以使用它执行许多不同的技巧。在内部,您可以将HWND视为GUI窗口表的索引(可能不一定是其实现方式,但这很有意义)。

编辑:不能100%肯定您在问什么。这主要是在谈论纯C / C ++。


13
句柄对于保存状态(以及其他状态)很有用。如果您在std :: vector这样的结构中有数据。在程序执行期间,您的对象可能在不同的时间位于不同的内存位置,这意味着指向该内存的指针将更改值。使用手柄,它永远不会改变,它始终引用您的对象。想象一下保存一个程序的状态(例如在游戏中)-您不会保存指向数据的指针位置,然后再重新导入数据并尝试在内存中获取该地址。但是,您可以将句柄与数据一起保存,然后导入数据和句柄。
SinisterRainbow 2012年

是否可以在Linux中将HANDLE转换为等效项?我必须将使用HANDLE的程序从Windows迁移到Linux。
Cornel Verster 2015年

1
这是正确的答案,它们可以是任何东西,并且使用它们的代码定义了句柄的类型。为了后代,我试图为自己的类似答案做一个更简洁的版本,这让我无济于事。@CornelVerster-在Linux中它们是相同的。我的意思是,不是操作系统处理,而是概念。因此,它取决于其迁移的句柄,甚至需要迁移。
dyasta

@Matthew Iselin:在任何API文档中,它们是否都将其定义为处理程序,然后我们应该知道将其传递给函数,否则我们如何才能知道API文档中的处理程序
Amin Khormaei

51

句柄是没有可见类型的指针或索引。通常,您会看到类似以下内容的内容:

 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);
     }
 }

29

句柄一种指针,因为它通常是引用某些实体的一种方式。

说一个指针是句柄的一种类型会更准确,但是并不是所有的句柄都是指针。

例如,句柄也可以是内存表中的某个索引,该表对应于本身包含指向某个对象的指针的条目。

关键是,当您拥有“句柄”时,您既不知道也不在乎该句柄实际上最终不会识别出它所识别的事物,您需要知道的就是它确实存在。

还应该显而易见的是,对于“什么才是真正的句柄”并没有一个唯一的答案,因为即使在同一系统中,对不同事物的句柄也可能以不同的方式“在幕后”实施。但是您不必担心这些差异。


6

在C ++ / CLI中,句柄是指向位于GC堆上的对象的指针。通过使用(在非托管的)C ++堆上创建对象可以实现,new并且new表达式的结果是“普通”指针。使用gcnew表达式在GC(托管)堆上分配托管对象。结果将是一个句柄。您不能对句柄执行指针运算。您没有释放把手。GC将照顾他们。此外,GC可以自由地在托管堆上重定位对象,并在程序运行时更新句柄以指向新位置。


5

这出现在Handle-Body-Idiom(也称为Pimpl惯用语)的上下文中。通过将实际数据保存到另一个类对象中,该类库可以使库的ABI(二进制接口)保持相同,该类对象仅由“句柄”对象中包含的指针引用,该指针由代表该类的函数组成。身体”。

启用两个对象的恒定时间和异常安全交换也很有用。为此,仅需交换指向主体对象的指针。


2

手柄是您想要的任何形状。

句柄可以是某些查找表中使用的无符号整数。

句柄可以是指向更大数据集或指向更大数据集的指针。

这取决于使用该句柄的代码的行为方式。这确定了句柄类型。

重要的是使用术语“ 手柄 ” 的原因。这表明它们是对象的标识或访问类型。对程序员来说,它们代表一个“钥匙” 对某物的访问。


2

HANDLE hnd; 是相同的 void * ptr;

HANDLE是在Visual Studio(Windows)的winnt.h文件中定义的typedef:

typedef void *HANDLE;

进一步了解HANDLE


1
这仅适用于Windows,并且仅适用于Windows体系结构中使用的多种类型的句柄之一。但是,这就是所谓的“普通Windows应用程序级句柄”。
dyasta
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.