转自:https://blog.csdn.net/Godsight/article/details/52738175

我觉得自己对于指针理解比较透彻了,但关于句柄的理解,就容易犯理解成指针的错误. 
一般说:句柄是资源(或项目)的唯一标识. 
俺觉得这其实说得很不明白的,现在我想问的是句柄到底是怎么标识资源的: 
1,句柄在32位机上是32位整型吗? 
2,当HANDLE handle;声明句柄时,handle是它的标识符吗?如int a;则a就是标识符. 
3,既然句柄是一个整型值,那么,它在内存的什么位置呢?栈上吗? 
4,句柄是通过在它所占内存中记录对象在内存中的首地址来"标识"对象的吗?如果是,那与指针在这方面就完全一样了.

可能有点玄,大家谈论下吧.

---------------------------------------------------------------

对句柄的认识 
之前在编写MFC程序的时候,有时会碰到句柄这一概念,由于对它一直不是很重视,所以并没有主动去了解它.随着不断深入学习MFC,特别是看完候先生的<<深入浅出MFC>>后,对句柄的实质产生了很大的兴趣,于是到处收集资料,现在总结一下. 
handle的中文意思主要有多种,一种是作为名词:柄,把柄;一种是作为动词:处理.硬要从中文意思来说的话,这两种中文意思都可以用来勉强解释句柄.例如一个锅的手柄,你只要抓住了它,你就可以很好地操作那个锅,不过很明显你只能通过锅的手柄来做一些诸如炒菜之类的事,你不可能是因为抓住了锅的手柄才能去看电视.不能的物体都会至少有一个属于它的"手柄".在MFC里面,有很多对象,例如对话框,窗口,画笔,显示器,打印机等,每个对象都会产生一个属于它自己的句柄.oh!慢着,似乎还没说清楚句柄的本质,下面再作详细的解说吧.

如果查看各种HANDLE的定义,如HDC,HPEN,HINSTANCE等等,你会发现有这样一个声明:

DECLARE_HANDLE(HDC);

再把DECLARE_HANDLE这个宏展开来看一下:

#define DECLARE_HANDLE(name) struct name##__ { int unused; }; 
typedef struct name##__ *name

这是什么意思?用HDC替换上面的name来看看,我们就得到了下面的一段代码:

struct HDC__

{

int unused;

};

typedef struct HDC__ *HDC

oh,原来句柄就是一个指向某一结构的指针,这个结构体只有一个成员,它是一个整数(不知为什么MS要把这个成员叫做unused,难道真的没有用吗?).

嗯,我们再看一个HANDLE的定义,在winnt.h头文件中,我们看到了HANDLE的定义:

typedef PVOID HANDEL;

PVOID是什么?再看它的定义:

typedef void *PVOID;

真相出来了,原来HANDLE不过是一个指向void型,即无类型的指针,嗯,目前的指针是32位的吧.其实也不能说HANDLE是一种指针,它只充当一种索引的作用.真的很难解释HANDLE是什么,再往下看看,只能意会吧,呵呵.

知道了HANDLE的本质(一个32位的整数,用16进制表示),再来说说HANDLE的作用.看我前面第二段的例子,你可以了解到为了控制一个物体,你需要找到它的"手柄".HANDLE就是充当win32下各种"物体"的"手柄".事实上,很多windows API都需要一个HANDLE作为输入参数,这是因为API需要和一些你看不见的对象打交道,这些对象是不能被你所移动或修改的,所以不能给你一个指针来对它进行操作.oh,指针的确是个好东西,它所拥有的能力实在太强大了,但所谓能力越大,责任越大,使用指针的时候千万要小心,不然会造成毁灭性的错误.所以,为了安全,还是给你一个HANDLE吧,通过这个HANDLE,你就可以对那些对象进行一些处理.HANDLE在这里充当什么角色呢?应该算是一个中间人吧,HANDLE是固定的,它不会变,但是对象的地址会变,当对象在内存中的位置发生改变后,我们不能通过之前的对象指针找到对象,怎么办呢?嗯,这时候HANDLE的用处就出来了,HANDLE就是用来记录对象的最新地址的.有点明白了吧?换一种说法吧,嗯,其实就是你知道HANDLE在哪里,但你不知道对象在哪里,而HANDLE知道对象在哪里,所以,只要你知道了HANDLE在哪里,你就能找到对象(尽管你还是不知那个对象住在内存的哪个地方,不过找到它就行了,不是吗?).嗯,是不是有点像索引的作用呢?为什么不给我们知道对象在内存中的位置呢?呵呵,操作系统怕你对它进行一些不利的操作啊.反正你通过HANDLE能让对象做它应该做的事,这就足够了.这就是封装吧,MS最喜欢做的事情,呵呵.

其实对于HANDLE的定义,MS公司也不能说得清清楚楚,把HANDLE翻译成句柄也是不太合适的,但有时就是这样,英文能理解的东西,翻译到中文反而就混乱了,所以"句柄"这个名词比较适合初学者,如我.那些有丰富编程经验的人一定不喜欢使用"句柄"这个名词吧,还是用handle这个原版英文单词比较容易理解

句柄是不同于指针的,但是实际上的操作有想通的地方。创建一个窗体,或者创建DC、BITMAP……都会有相应的句柄产生。那么这些对象销毁的时候,他们对应的句柄也就失效了。或者说可以通过他们的句柄来销毁这些对象。

句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址 访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化 了。如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门 登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定)→实际对象。但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成 是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电 影院售给我们的门票总是不同的一个座位是一样的道理。

HDC是设备描述表句柄。

CDC是设备描述表类。

用GetSafeHwnd和FromHandle可以互相转换

指针可以当句柄

句柄不一定都是指针

句柄只是代表某一个对象的一个数字

根据这个数字可以通过某种关系找到这个对象

指针是一个对象的地址

::ReleaseDC();

这句话是释放HDC的句柄,还是释放HDC句柄所指的内存?

DC是设备上下文,用起来就像一根可以换笔蕊的笔壳.

是不是只有某些对像有句柄?

int i;

int* p=&i;

他的内存不会改变吧

句柄简而言之就是指向结构的指针。

::ReleaseDC();

int ReleaseDC(

HWND hWnd, // handle to window

HDC hDC     // handle to device context

);

C++-------对handle的理解相关推荐

  1. C++HANDLE的理解

    HANDLE:句柄,是WINDOWS用来表示对象的,是一个通用句柄表示. 在WINDOWS程序中,有各种各样的资源(窗口.图标.光标等),系统在创建这些资源时为他们分配内存,并返回标示这些资源的标示号 ...

  2. 关于对handle的理解

    从本人有限的C99.C++11.java8.matlab2012.python3.x 的有限经验来看. handle这个关键字最初是在windows编程的书中提到的,在matlab的GUI的编程中也有 ...

  3. curl 请求没反应_理解Redis的反应堆模式

    本文首发于: 理解Redis的反应堆模式​mp.weixin.qq.com 微信公众号:后端技术指南针 欢迎关注 接收最新文章! 1. Redis的网络模型 Redis基于Reactor模式(反应堆模 ...

  4. UEFI Handle与Protocol

    最近看了一些UEFI中handle和protocol的资料,这里做一个整理,写一点自己的理解,想了想还是搬运过来了,因为写得比较认真,但是放github 博客上除了我应该没人看吧. 主要参考文章 UE ...

  5. Linux tcpdump命令详解与Wireshark

    简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...

  6. 3w字深度好文|Redis面试全攻略,读完这个就可以和面试官大战几个回合了

    0x00.前言 众所周知数据结构和算法是面试重点,我们持续发力是十分明智的,要不然最后肯定是要吃亏的,少打打游戏刷刷微博可以改变我们的生活水平哦. 不过本文不是要讲述数据结构和算法的,而是另外一个面试 ...

  7. Linux 常用命令标记

    1.linux 服务器之间拷贝文件 scp 本地用户名@IP地址:文件名1 远程用户名@IP地址:文件名2 该命令可以变型为目的服务器204上输入如下命令:红色部分是需要接受目的地,-r是递归复制该文 ...

  8. tcpdump的简单选项介绍

    tcpdump采用命令行方式,它的命令格式为: tcpdump [ -AdDeflLnNOpqRStuUvxX ] [ -c count ] [ -C file_size ] [ -F file ] ...

  9. Linux tcpdump命令

    一.简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据 ...

最新文章

  1. 关于startActivityForResult
  2. 脑机接口需要我们掌握什么样的知识?
  3. kompozer+mysql_KompoZer for mac下载_KompoZer for mac版V0.8b3下载(暂未上线)_预约_飞翔下载...
  4. 开放搜索开源兼容版,支持Elasticsearch做搜索召回引擎
  5. 99.999%,提升ElasticSearch稳定性的秘密
  6. 《Migrating to Cloud-Native Application Architectures》学习笔记之Chapter 2. Changes Needed
  7. PingCAP联合创始人兼CTO黄东旭:致力于打造全球最好的分布式数据库
  8. php 5.3.29 怎么开启debug_PHP代码审计之环境安装(一)
  9. Bailian3711 字符串移位包含问题【字符串循环匹配】(POJ NOI0107-19)
  10. SpringBoot2整合Shiro实现权限管理
  11. 线性回归 python_python中的线性回归
  12. ESP8266WiFi模块实现代码
  13. 实型变量的定义和应用
  14. [USACO 2008 MAR] 土地购买
  15. 功能超级强大的计算器程序 免费开源 全部源码
  16. java毕业设计葡萄酒销售管理系统mybatis+源码+调试部署+系统+数据库+lw
  17. 简化版的DRCNN代码(Python)
  18. 计算机知识竞赛策划案,计算机知识竞赛策划书范文
  19. 小白学3D建模推荐3dsMax,这些功能你必须知道!
  20. Linux安装部署DM8详细步骤与问题解决

热门文章

  1. XDOJ数字排序/选号程序
  2. FATFS 的几个函数使用方法
  3. spark如何进行聚类可视化_基于Spark的出租车轨迹处理与可视化平台
  4. SEO排名,站内与站外优化的策略!
  5. wxpython 按钮 扁平化_tensorflow tensor Flatten 张量扁平化,多通道转单通道数据
  6. 如何快速成为一个游戏测试工程师(配教程)
  7. Ajax 查询手机号码归属地
  8. 聊聊这个火爆GitHub的女装大佬项目
  9. 3000万!近两年边缘计算领域招投标项目汇总
  10. 最美手机 魅族魅蓝X幻影蓝/曜石黑上市