“句柄”是什么意思

本文解释了计算机中的句柄概念,句柄是一个标识符,用于标识应用程序创建或使用的对象,如窗口、控件等。它是指向指针的指针,帮助应用程序在内存中定位这些对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://www.cnitblog.com/cockerel/archive/2006/07/04/13224.aspx


所谓句柄实际上是一个数据,是一个Long (整长型)的数据。 

句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。 

从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。 

如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢? 

为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。 


句柄地址(稳定)→记载着对象在内存中的地址————→对象在内存中的地址(不稳定)→实际对象 


本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。 


但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。

### C++ 中句柄的概念、定义与用法 #### 什么是句柄? 在 C++ 编程中,句柄通常被理解为一种间接访问资源的方式。具体来说,句柄是一个指向某个对象或资源的引用机制[^4]。它可以表示文件、窗口、设备上下文或其他系统资源的对象。通过句柄,程序可以操作这些底层资源而无需直接管理其复杂细节。 #### 句柄的作用 句柄的主要作用是简化对复杂数据结构的操作,并提供抽象层以便于管理和维护资源。例如,在 Windows 系统中,许多 API 函数会返回一个句柄作为结果,用于后续对该特定资源的操作。如果未正确关闭句柄,则可能导致资源泄漏等问题。 #### C++ 中句柄的具体实现方式 C++ 的句柄可以通过多种方式进行设计和实现,其中较为常见的有以下几种: 1. **智能指针模式下的句柄** 使用智能指针(如 `std::shared_ptr` 或自定义封装)来构建句柄类是一种现代做法。这种方式不仅提供了自动内存管理功能,还支持引用计数等特性。 下面展示了一个简单的句柄类示例: ```cpp class Base { public: virtual ~Base() {} virtual void use() const = 0; virtual int compute() const = 0; }; template<typename T> class Handle { private: T* ptr; public: explicit Handle(T* t) : ptr(t) {} ~Handle() { delete ptr; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } }; ``` 2. **基于引用计数的句柄** 这种类型的句柄类似于 COM 对象中的引用计数模型。每当复制一份句柄时,都会增加引用计数;当销毁某份副本时则减少引用计数。一旦引用计数降为零,就会释放关联的实际对象及其占用的资源。 如下所示的是一个典型的引用计数型句柄的设计片段: ```cpp struct Item_base {}; class Handle_item { private: Item_base* p; std::size_t* cnt; public: Handle_item(const Item_base& item) : p(item.clone()), cnt(new std::size_t(1)) {} Handle_item(const Handle_item& h) : p(h.p), cnt(h.cnt) { ++(*cnt); } ~Handle_item() { if (--(*cnt) == 0) { delete p; delete cnt; } } Handle_item& operator=(const Handle_item&); }; ``` 3. **实际应用案例——多态场景下的句柄运用** 结合虚函数表机制,可以在运行期动态决定调用哪个派生类成员函数版本。这使得即使基类指针也能安全地执行子类特化行为。 示例代码如下: ```cpp #include <iostream> using namespace std; class Base { protected: int data; string name; public: Base(int d, string n) : data(d), name(n) {} virtual void use() const { cout << "Using base object named: " << name << endl; } virtual int compute() const { return data * 2; } virtual ~Base() {} }; class Derived : public Base { public: Derived(int d, string n, double factor) : Base(d, n), fact(factor) {} void use() const override { cout << "Using derived object with factor: " << fact << ", Name: " << this->name << endl; } int compute() const override { return static_cast<int>(this->data * fact); } private: double fact; }; int main() { Handle<Base> h1(new Base(2, "Base")); h1.use(); cout << "Base compute:" << (*h1).compute() << endl; Handle<Derived> h2(new Derived(3, "derived", 3)); h2.use(); cout << "Derived compute:" << (*h2).compute() << endl; return 0; } ``` 上述例子展示了如何利用模板参数化的句柄类处理不同类型的继承关系实例[^2]。 #### 常见注意事项 - 需要注意防止循环依赖导致无法正常回收资源的情况发生。 - 如果涉及跨模块传递句柄,请确保接收方具备足够的权限去解构原始对象。 - 正确初始化和清理句柄所持有的资源非常重要,否则容易引起各种难以追踪的问题,比如野指针错误或者双重删除异常等等[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值