Windows桌面应用程序(1-2-3-6th) 管理对象的生命周期
2018-03-30 22:29
295 查看
对于我们尚未提及的COM接口有一个规则。每个COM接口必须直接或间接地从名为IUnknown的接口继承。该接口提供了所有COM对象必须支持的一些基线功能。
该IUnknown接口定义了三个方法:
QueryInterface
AddRef
Release
该QueryInterface方法可以使程序在运行时查询对象的能力。我们将在下一个主题“ 为接口询问对象”中详细说明。所述AddRef和Release方法用于控制一个对象,这是本主题的主题的寿命。
引用计数
无论程序可以做什么,在某个时候它都会分配和释放资源。分配资源很容易。了解何时释放资源非常困难,特别是如果资源的生命周期超出当前范围。这个问题不是COM独有的。任何分配堆内存的程序都必须解决同样的问题。已经设计了各种解决方案,包括自动析构函数(C ++)和垃圾回收(C#,Java,Lisp)。COM使用称为引用计数的方法。
每个COM对象都维护一个内部计数,称为引用计数。引用计数跟踪对象当前活动的引用数量。当引用的数量下降到零时,对象将自行删除。最后一部分值得重复:对象删除自己; 该程序从不显式删除该对象。
以下是参考计数的规则:
首次创建对象时,其引用计数为1.此时,程序具有指向该对象的单个指针。
该程序可以通过复制指针来创建新的参考。每当您复制指针时,都必须调用对象的AddRef方法。此方法将引用计数加1。
当您完成使用指向该对象的指针时,您必须调用Release。Release方法减一的引用计数。它也使指针无效。致电Release后请勿再次使用指针。(如果你有指向同一个对象的其他指针,你可以继续使用这些指针。)
当您使用每个指针调用Release时,对象的引用计数将达到零,并且该对象将自行删除。
下图显示了一个简单但典型的案例。
显示参考计数的插图
该程序创建一个对象并将一个指针(p)存储到该对象。此时,引用计数为1.当程序使用指针完成时,它调用Release。引用计数递减到零,并且对象删除自己。现在p是无效的; 将p用于任何其他方法调用是错误的。
下图显示了一个更复杂的例子。
显示参考计数的插图
在这里,程序像以前一样创建一个对象并存储指针p。接下来,程序将p复制到一个新变量q中。此时,程序必须调用AddRef来增加引用计数。引用计数现在是2,并且有两个指向对象的有效指针。现在假设程序使用p完成。程序调用Release,引用计数变为1,并且p不再有效。但是,q仍然有效。稍后,程序使用q完成,因此它再次调用Release。引用计数变为零,并且对象删除自身。
你可能想知道为什么这个程序首先要复制p。主要有两个原因:首先,您可能希望将指针存储在数据结构中,如列表。其次,您可能希望将指针保留在原始变量的当前范围之外,以便将其复制到范围更广的新变量中。
引用计数的一个优点是,您可以共享指向不同代码段的指针,而不需要各种代码路径协调删除对象。相反,每个代码路径只需在该代码路径使用该对象完成时调用Release。该对象负责在正确的时间删除自己。
例
这里是再次打开对话框示例中的代码。
引用计数发生在两个地方。首先,如果程序成功创建Common Item Dialog对象,它必须在pFileOpen指针上调用Release。
其次,当GetResult方法返回指向IShellItem接口的指针时,程序必须在pItem指针上调用Release。
请注意,在这两种情况下,Release调用都是指针超出范围之前发生的最后一件事。另请注意,只有在测试成功HRESULT后才会调用Release。例如,如果对CoCreateInstance的调用失败,则pFileOpen指针无效,因此在指针上调用Release将会出错。
下一个
请求接口的对象
该IUnknown接口定义了三个方法:
QueryInterface
AddRef
Release
该QueryInterface方法可以使程序在运行时查询对象的能力。我们将在下一个主题“ 为接口询问对象”中详细说明。所述AddRef和Release方法用于控制一个对象,这是本主题的主题的寿命。
引用计数
无论程序可以做什么,在某个时候它都会分配和释放资源。分配资源很容易。了解何时释放资源非常困难,特别是如果资源的生命周期超出当前范围。这个问题不是COM独有的。任何分配堆内存的程序都必须解决同样的问题。已经设计了各种解决方案,包括自动析构函数(C ++)和垃圾回收(C#,Java,Lisp)。COM使用称为引用计数的方法。
每个COM对象都维护一个内部计数,称为引用计数。引用计数跟踪对象当前活动的引用数量。当引用的数量下降到零时,对象将自行删除。最后一部分值得重复:对象删除自己; 该程序从不显式删除该对象。
以下是参考计数的规则:
首次创建对象时,其引用计数为1.此时,程序具有指向该对象的单个指针。
该程序可以通过复制指针来创建新的参考。每当您复制指针时,都必须调用对象的AddRef方法。此方法将引用计数加1。
当您完成使用指向该对象的指针时,您必须调用Release。Release方法减一的引用计数。它也使指针无效。致电Release后请勿再次使用指针。(如果你有指向同一个对象的其他指针,你可以继续使用这些指针。)
当您使用每个指针调用Release时,对象的引用计数将达到零,并且该对象将自行删除。
下图显示了一个简单但典型的案例。
显示参考计数的插图
该程序创建一个对象并将一个指针(p)存储到该对象。此时,引用计数为1.当程序使用指针完成时,它调用Release。引用计数递减到零,并且对象删除自己。现在p是无效的; 将p用于任何其他方法调用是错误的。
下图显示了一个更复杂的例子。
显示参考计数的插图
在这里,程序像以前一样创建一个对象并存储指针p。接下来,程序将p复制到一个新变量q中。此时,程序必须调用AddRef来增加引用计数。引用计数现在是2,并且有两个指向对象的有效指针。现在假设程序使用p完成。程序调用Release,引用计数变为1,并且p不再有效。但是,q仍然有效。稍后,程序使用q完成,因此它再次调用Release。引用计数变为零,并且对象删除自身。
你可能想知道为什么这个程序首先要复制p。主要有两个原因:首先,您可能希望将指针存储在数据结构中,如列表。其次,您可能希望将指针保留在原始变量的当前范围之外,以便将其复制到范围更广的新变量中。
引用计数的一个优点是,您可以共享指向不同代码段的指针,而不需要各种代码路径协调删除对象。相反,每个代码路径只需在该代码路径使用该对象完成时调用Release。该对象负责在正确的时间删除自己。
例
这里是再次打开对话框示例中的代码。
HRESULT hr=CoInitializeEx(NULL,COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE); if(SUCCEEDED(hr)){ IFileOpenDialog *pFileOpen; hr=CoCreateInstance(CLSID_FileOpenDialog,NULL,CLSCTX_ALL,IID_IFileOpenDialog,reinterpret_cast<void**>(&pFileOpen)); if(SUCCEEDED(hr)){ hr=pFileOpen->Show(NULL); if(SUCCEEDED(hr)){ IShellItem *pItem; hr=pFileOpen->GetResult(&pItem); if(SUCCEEDED(hr)){ PWSTR pszFilePath; hr=pItem->GetDisplayName(SIGDN_FILESYSPATH,&pszFilePath); if(SUCCEEDED(hr)){ MessageBox(NULL,pszFilePath,L"File Path",MB_OK); CoTaskMemFree(pszFilePath); } pItem->Release(); } } pFileOpen->Release(); } CoUninitialize(); }
引用计数发生在两个地方。首先,如果程序成功创建Common Item Dialog对象,它必须在pFileOpen指针上调用Release。
hr=CoCreateInstance(CLSID_FileOpenDialog,NULL,CLSCTX_ALL,IID_IFileOpenDialog,reinterpret_cast<void**>(&pFileOpen)); if(SUCCEEDED(hr)){ // ... pFileOpen->Release(); }
其次,当GetResult方法返回指向IShellItem接口的指针时,程序必须在pItem指针上调用Release。
hr=pFileOpen->GetResult(&pItem); if(SUCCEEDED(hr)){ // ... pItem->Release(); }
请注意,在这两种情况下,Release调用都是指针超出范围之前发生的最后一件事。另请注意,只有在测试成功HRESULT后才会调用Release。例如,如果对CoCreateInstance的调用失败,则pFileOpen指针无效,因此在指针上调用Release将会出错。
下一个
请求接口的对象
相关文章推荐
- Windows桌面应用程序(1-2-3-4th) 在COM中创建一个对象
- (Mirage系列之一)使用VMware Horizon Mirage进行灵活高效的Windows桌面分层、灾备、迁移及应用程序管理
- Windows桌面应用程序(1-2-4-6th) 使用Direct2D绘图
- QtQuick桌面应用程序开发指南 4)动态管理Note对象_B 5)加强外观 6)许多其他的改进
- Windows桌面应用程序(1-2-5-6th) 加速器表
- Windows桌面应用程序(1-2-2-6th) 管理应用程序状态
- Windows桌面应用程序(1-2-2-2nd) 窗口消息
- Windows桌面应用程序(1-2-1st) Windows编程简介在C++中
- [原创]我所理解的Remoting(2):远程对象生命周期的管理—Part I
- hibernate 管理Session:Session 对象的生命周期与本地线程绑定
- windows下应用程序的快捷方式管理
- [原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定
- Delphi 接口使用中,对象生命周期管理,如何释放需要注意的问题
- C#编写Windows桌面应用程序在窗体上滚动字幕
- 用HTML开发Windows桌面应用程序2
- SharePoint 创建列表并使用Windows Presentation Foundation应用程序管理列表
- netty的对象的生命周期管理——引用计数
- 自己管理对象生命周期中Delphi接口的一个问题
- 远程桌面新体验—Windows Multipoint Server 2012 客户端远程访问及管理
- SharePoint 2010应用程序生命周期管理(一)