当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++基础入门教程

C++智能指针应用分析

一:关于纠错,MFC和ATL中智能指针的应用

  1:在Windows中如何方便的查看当前进程使用的内存。

  虽然代码简单,但对纠错时有大用处,不用不停的通过切换任务管理器来查看内存使用。代码如下:

UINT C_BaseUtil::getProcessMemoryUsed()
{
 UINT uiTotal = 0L;
 HANDLE hProcess = ::GetCurrentProcess();
 PROCESS_MEMORY_COUNTERS pmc;
 if(::GetProcessMemoryInfo(hProcess,&pmc,sizeof(pmc)))
  uiTotal = pmc.WorkingSetSize;
 return uiTotal;
}

  注意:由于内存使用会是一个不稳定的过程,所以,需要在程序稳定时进行调用,才能准确。

  2:在使用Com的Dispatch指针时,如果不使用COM智能指针,容易出现的错误。

  2.1:忘记在所有出口释放指针。
  
  如:

IXMLDOMDocument *pDoc = NULL;
CoCreateInstance(...)
……
pDoc->Release();

  错误:如果中间代码发生异常,则pDoc未能正常释放,造成内存泄露。

  2.2:重复使用同一指针变量,导致中间生成的Dispatch指针未能释放。

IXMLDOMNode *pNode = NULL;
if(FAILED(pDoc->selectSingleNode(_bstr_t(\"Workbook\"), &pNode)) || pNode==NULL)
throw(_T(\"selectSingleNode failed!\"));
if(FAILED(pDoc->selectSingleNode(_bstr_t(\"Workbook\"), &pNode)) || pNode==NULL)
throw(_T(\"selectSingleNode failed!\"));

  错误:pNode未释放就开始第二次调用,造成内存泄露。或者类似pNode = pNode2的这种写法,也随手就出问题了。必须调用if(pNode) {pNode->Release();pNode=NULL;}

  3:使用MFC提供的Com智能指针解决上述问题。

  注意:可通过查看源码,看到#import生成的智能指针的原型是_com_ptr_t。

  3.1:

IXMLDOMDocumentPtr docPtr = NULL;
docPtr.CreateInstance(...)
……

  这下不会有问题了,因为docPtr在析构时会有正确的释放处理。

  3.2:

IXMLDOMNodePtr nodePtr = NULL;
if(FAILED(pDoc->selectSingleNode(_bstr_t(\"Workbook\"), &nodePtr)) || nodePtr==NULL)
throw(_T(\"selectSingleNode failed!\"));
if(FAILED(pDoc->selectSingleNode(_bstr_t(\"Workbook\"), &nodePtr)) || nodePtr==NULL)
throw(_T(\"selectSingleNode failed!\"));

  不会出错了,因为_com_ptr_t重载了&操作符,在取指针时,有如下操作,嘿。

Interface** operator&() throw()
{
 _Release();
 m_pInterface = NULL;
 return &m_pInterface;
}

  3.3: nodePtr = nodePrt2 ,也不会有问题:

  仔细查看源码,在=操作符中会调用Attach,而Attach的做法是:会先调用_Release();

  3.4:再看看值传递:拷贝构造函数如下

template<> _com_ptr_t(const _com_ptr_t& cp) throw()
: m_pInterface(cp.m_pInterface)
{
 _AddRef();
}

  嗯,也不会有问题。

  3.5:最后我们也总结一下使用COM智能指针时的注意事项:

  ·不要在Com智能指针的生命期如果在::CoUninitailize之后,那请在调用::CoUninitailize之前,强制调用MyComPtr = NULL;达到强制释放的目的。否则会出错。

  ·不要混用智能指针和普通Dispatch指针,不要调用MyComPtr->Release(),这违背智能指针的原意,会在析构时报错。

  4:使用ATL提供智能指针:CComPtr或是CComQIPtr.

  如果不使用MFC框架,要自已包装IDispatch,生成智能指针,还可以使用ATL提供的智能指针。查看源码,并参照《深入解析ATL》一书,发现实现与_com_ptr_t大同小异,效果一致。

  二:引申一下,我们来看看C++的智能指针

  1:说到智能指针,我们一定要看看标准C++提供的auto_ptr。而auto_ptr的使用是有很多限制的,我们一条一条来细数:

  1.1:auto_ptr要求一个对象只能有一个拥有者,严禁一物二主。

  比如以下用法是错误的。

classA *pA = new classA;
auto_ptr<classA> ptr1(pA);
auto_ptr<classA> ptr2(pA);


  1.2:auto_ptr是不能以传值方式进行传递的。

  因为所有权的转移,会导致传入的智能指针失去对指针的所有权。如果要传递,可以采用引用方式,利用const引用方式还可以避免程序内其它方式的所有权的转移。就其所有权转移的做法:可以查看auto_ptr的拷贝构造和=操作符的源码,此处略。

  1.3:其它注意事项:

  ·不支持数组。

  ·注意其Release语意,它没有引用计数,与com提供的智能指针不同。Release是指释放出指针,即交出指针的所有权。

  ·auto_ptr在拷贝构造和=操作符时的特珠含义决定它不能做为STL标准容器的成员,

  好了,看了上面的注意事项,特别是第三条,基本上可以得出结论:在实际应用场合,auto_ptr基本没什么应用价值的。

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接