msdn在介绍GetDlgItem的时候,明确指出:  
The  returned  pointer  may  be  temporary  and  should  not  be  stored  for  later  use.  
如果真是这样那我不惨了!在我的一个软件中,因为常常要使切换按钮的可用与不可用以及改变按钮文字,所以我用DetDlgItem把它们存了起来,用的时候直接到数组里面取,这样的话这个软件不是犯了一个重大的错误了?可是用这么久也没出错。  
另外,它也是说可能是临时的,那一定在某种情况下不是临时的,高手能不能解释一下这个问题?  
---------------------------------------------------------------  
//    Most  Windows  objects  are  represented  with  a  HANDLE,  including  
//            the  most  important  ones,  HWND,  HDC,  HPEN,  HFONT  etc.  
//    We  want  C++  objects  to  wrap  these  handle  based  objects  whenever  we  can.  
//    Since  Windows  objects  can  be  created  outside  of  C++  (eg:  calling  
//            ::CreateWindow  will  return  an  HWND  with  no  C++  wrapper)  we  must  
//            support  a  reasonably  uniform  mapping  from  permanent  handles  
//            (i.e.  the  ones  allocated  in  C++)  and  temporary  handles  (i.e.  
//            the  ones  allocated  in  C,  but  passed  through  a  C++  interface.  
//    We  keep  two  dictionaries  for  this  purpose.    The  permanent  dictionary  
//            stores  those  C++  objects  that  have  been  explicitly  created  by  
//            the  developer.    The  C++  constructor  for  the  wrapper  class  will  
//            insert  the  mapping  into  the  permanent  dictionary  and  the  C++  
//            destructor  will  remove  it  and  possibly  free  up  the  associated  
//            Windows  object.  
//    When  a  handle  passes  through  a  C++  interface  that  doesn't  exist  in  
//            the  permanent  dictionary,  we  allocate  a  temporary  wrapping  object  
//            and  store  that  mapping  into  the  temporary  dictionary.  
//    At  idle  time  the  temporary  wrapping  objects  are  flushed  (since  you  better  
//            not  be  holding  onto  something  you  didn't  create).  
//  
 
 
在CWinThread::OnIdle里调用AfxUnlockTempMaps,AfxUnlockTempMaps会释放temporary  maps.  
 
所以不要保留GetDlgItem等返回的临时指针,可以直接保存HWND  objects,然后CWnd::FromHandle获取临时指针来用。  
 
---------------------------------------------------------------  
 
临时包装对象会在空闲时间删除.在同一函数中多次使用是没用问题的,不同函数中使用先前保存下来的指针就有可能出错,特别是对话框初使化时候存下来的指针.  
       在MFC层次上的函数使用CWnd对象,而本地Windows代码(API)使用句柄.如:当Windows系统调用一个窗口过程时将传递一个HWND参数,而MFC本身的消息机制使用CWnd类;为了更好更高效的实现,MFC需要与Windows系统合作,将句柄与CWnd对象进行关联---它用CHandleMap完成关联.  
CHandleMap有两个CMapPtrToPtr的成员变量:m_permanentMap(永久映射表,程序运行过程中对象/句柄之间的关系),m_temporaryMap(临时映射表,在消息存在的过程中才存在).永久表保存显式创建的CWnd对象,当对象创建时将在永久目录下插入一个条目,在CWnd::OnNcDestrory时删除对应条目.但是Windows有时会传入某些不是由开发人员显式创建的窗口的句柄,此时MFC会分配一个临时对象来包装这个句柄并将它们的映射保存到临时映射表中,这些临时对象会在空闲时间被删除并移走相应的临时映射表条目.类似的MFC对象与Windows句柄的映射表有:  
m_pmapHWND:                        窗口句柄与CWnd对象  
m_pampHMENU:                        菜单句柄与CMenu对象  
m_pmapHDC:                        设备环境句柄与CDC对象  
m_pmapHGDIOBJ:                        GDI句柄与CGDI对象  
m_mapHIMAGELIST:            图像链表句柄到CImageList对象  
 
当给定句柄,如HWND时,MFC简单调用CWnd*  PASCAL  CWnd::FromHandle(HWND  hWnd),  此函数内部使用CHandleMap::FromHandle(hWnd)获取相关联的CWnd对象.在CHandleMap::FromHandle(h)内部(源代码在WinHand.cpp),先使用CObject*  pObject  =  LookupPermanent(h);            if  (pObject  !=  NULL)return  pObject;    检查永久表;如永久表中不存在,使用pObject  =  LookupTemporary(h))  !=  NULL检查临时表,都不存在时,使用pTemp  =  =  m_pClass->CreateObject();if  (pTemp  ==  NULL)AfxThrowMemoryException();m_temporaryMap.SetAt((LPVOID)h,  pTemp);创建临时对象并将其插入到临时表中去,同时返回该临时对象.  
void  CHandleMap::RemoveHandle(HANDLE  h)的注释说明临时对象将在空闲时由OnIdel释放:  
           //  remove  only  from  permanent  map  --  temporary  objects  are  removed  
           //    at  idle  in  CHandleMap::DeleteTemp,  always!  
如果想不自动释放临时对象,使用void  AFXAPI  AfxLockTempMaps()/BOOL  AFXAPI  AfxUnlockTempMaps(BOOL  bDeleteTemps)进行锁定.

MFC返回的临时对象指针成因?相关推荐

  1. c/c++进阶之爱恨交织的临时对象: 二、天使与魔鬼

    c/c++语言最让人称道的便是性能了,在大气科学.地球物理等等需要高性能计算方面c/c++语言都是不二之选.甚至在分布式领域,由于ssd固态硬盘和万兆网络的兴起,当IO不再成为分布式系统的瓶颈,CPU ...

  2. 【读书笔记】【程序员的自我修养 -- 链接、装载与库(三)】函数调用与栈(this指针、返回值传递临时对象构建栈、运行库与多线程、_main函数、系统调用与中断向量表、Win32、可变参数、大小端

    文章目录 前言 介绍 内存 内存布局 栈与调用惯例 堆与内存管理 运行库 入口函数和程序初始化 C/C++运行库 运行库与多线程 C++全局构造与析构 fread 实现 系统调用与API 系统调用介绍 ...

  3. MFC通过对话框窗口句柄获得对话框对象指针

    mfc如何获得控件句柄 CWnd *pWnd = GetDlgItem(ID_***); // 取得控件的指针 HWND hwnd = pWnd->GetSafeHwnd(); // 取得控件的 ...

  4. std::ostringstream::str()返回临时对象

    取得std::ostringstream里的内容可以通过str()和str(string&)成员函数.由于str()返回的是临时对象,因而会有如下误用: const char *  pBuff ...

  5. 提高C++性能的编程技术笔记:临时对象+测试代码

    类型不匹配:一般情况是指当需要X类型的对象时提供的却是其它类型的对象.编译器需要以某种方式将提供的类型转换成要求的X类型.这一过程可能会产生临时对象. 按值传递:创建和销毁临时对象的代价是比较高的.倘 ...

  6. C++之临时对象、常引用和浅拷贝探究

      和结构体一样,一个类的对象也可以以值,指针或者引用的形式作为函数的参数或返回值.一般情况下,为了避免创建临时对象通常传对象的引用,并且为了避免在函数体内修改对象的值,通常使用常引用:     co ...

  7. MFC 教程【5_MFC对象的创建】

    MFC对象的创建 前面几章介绍了MFC的核心概念和思想,即介绍了MFC对Windows对象的封装方法和特点:MFC对象的动态创建.序列化:MFC消息映射机制. 现在,考查MFC的应用程序结构体系,即以 ...

  8. 【Effection C++】读书笔记 条款28:避免返回handles指向对象内部成分

    [Effective C++]读书笔记 Part5 实现 条款28:避免返回handles指向对象内部成分 避免返回handles(包括references,指针,迭代器)指向对象内部.遵守这个条款可 ...

  9. Go 学习笔记(18)— 函数(04)[闭包定义、闭包修改变量、闭包记忆效应、闭包实现生成器、闭包复制原对象指针]

    1. 闭包定义 Go 语言中闭包是引用了自由变量的函数,被引用的自由变量和函数一同存在,即使已经离开了自由变量的环境也不会被释放或者删除,在闭包中可以继续使用这个自由变量,因此,简单的说: 函数 + ...

最新文章

  1. PYTHON自动化Day12-unittest自动注册登录
  2. 【深度学习】2021年深度学习哪些方向比较新颖,处于上升期或者朝阳阶段,没那么饱和,比较有研究潜力?...
  3. usnews 计算机专业排名,2019美国大学USNews计算机专业排名
  4. wordpress主题 阿里百秀XIU v7.7版本
  5. java开源播放器_JavaFX/Java8开发的开源音乐播放器
  6. C++_类和对象_封装_成员属性私有化---C++语言工作笔记038
  7. [CLR via C#]1.6 Framework类库~1.9与非托管代码的互操作性
  8. 《流畅的Python》读书笔记——Python一等函数
  9. 正则表达式--简单记忆一
  10. 循环结构程序设计学习心得
  11. JAVA系统学习之三大版本JavaSE、javaEE、javaME
  12. Netbeans 7.1 add android plugin
  13. 推荐10个堪称神器的学习网站,IT学习网站
  14. 计算机组成原理 原码,反码,补码,移码
  15. 软件测试周刊(第36期):为什么你要当程序员?
  16. 对于自定义element 弹出框 文字提示样式
  17. 手机端扫描证件识别SDK
  18. HDU 2007 平方和与立方和
  19. VC操作excel表格
  20. 最详细的ensp安装及使用

热门文章

  1. HDFS体系架构介绍
  2. 5000字干货原创 | APP版本迭代如何避免踩坑?
  3. 2020年中国智能客服行业研究报告
  4. android8.0更新手机,安卓微信8.0.6正式更新:可发1G大文件、表情互动等多项更新!...
  5. mac android屏幕演示,如何在Mac上录制Android设备的屏幕 | MOS86
  6. 作者:李俊清,山东农业大学副教授。
  7. 作者:连德富,男,电子科技大学讲师、教育大数据研究所副所长。
  8. 作者:许洪波,男,博士,中国科学院计算技术研究所副研究员、硕士生导师。...
  9. 移动应用开发——实验五
  10. 【操作系统】页置换算法