首页 > 程序开发 > 软件开发 > C语言 >

有效的使用和设计COM智能指针—条款3:选择合适的智能指针

2011-09-15

条款3:按照功能和实现原理选择合适的智能指针智能指针种类繁多,从实现原理上可以划分为基于所有权传递和基于引用计数两大类。C++中内置的std::auto_ptr则为基于所有权传递的智能指针。而Boost库中的shared_ptr...

条款3:按照功能和实现原理选择合适的智能指针
智能指针种类繁多,从实现原理上可以划分为“基于所有权传递”和“基于引用计数”两大类。C++中内置的std::auto_ptr则为“基于所有权传递”的智能指针。而Boost库中的shared_ptr则是“基于引用技术”的智能指针(目前已经成为C++0x【6】的一部分)。

如“基于所有权传递”的智能指针会在将自己赋值给其他智能指针或者普通指针后将自己置空。这样资源对象的权限被“移交”出去,使得每个资源在一个时候仅仅有一个拥有者持有其访问权限。如std::auto_ptr便是这样的指针:

view plaincopy to clipboardprint?auto_ptr<int> ap1(new int(0));
auto_ptr<int> ap2 = ap1;
cout<<*ap1; //错误,此时ap1只剩一个null指针在手了
auto_ptr<int> ap1(new int(0));
auto_ptr<int> ap2 = ap1;
cout<<*ap1; //错误,此时ap1只剩一个null指针在手了

这种智能指针简单,且能尽早的发现错误(不像引用计数错误后导致难以查找的问题。)智能指针对资源的唯一所有权,使得其很明确的知道什么时候需要对其释放。

而缺点也是很明显的:资源共享不方便。且无法将这类指针放置于STL这样的标准类模版中【7】。因为STL参数传递都采用的是值传递,而非引用传递。试想一下,若放置一个智能指针在容器中,而后只是通过容器访问了一下此指针,容器中的指针就指向NULL了,情况是多么糟糕。

而“基于引用计数”的智能指针则会在智能指针内部维持一个引用计数。当产生一份智能指针的拷贝(如将一个智能指针赋值到另一个智能指针)则引用计数递增一次,若智能指针出栈,则析构函数会让引用计数递减一次。若当引用计数为0则表明没有任何智能指针再指向这个资源对象了,此时智能指针会对资源进行销毁。

COM的智能指针都采用这种方式实现,因为COM本生就采用引用计数,而且需求上也要求COM能被多个指针访问,这些指针都应当有COM组件的所有权。如下:

view plaincopy to clipboardprint?CComPtr<IX> spIX = NULL;
HRESULT hr = spIX.CoCreateInstance(CLSID_MYCOMPONENT);
If(SUCCEEDED(hr))
{
spIX->Fx();
CComPtr<IX> spIX2 = spIX;//赋值操作会使得原来的引用计数递增。
spIX2->Fx();
spIX->Fx(); //赋值运算后,原来的智能指针还是能继续使用。
}//智能指针析构的时候递减其引用计数,并决定是否销毁其所拥有的资源

CComPtr<IX> spIX = NULL;
HRESULT hr = spIX.CoCreateInstance(CLSID_MYCOMPONENT);
If(SUCCEEDED(hr))
{
spIX->Fx();
CComPtr<IX> spIX2 = spIX;//赋值操作会使得原来的引用计数递增。
spIX2->Fx();
spIX->Fx(); //赋值运算后,原来的智能指针还是能继续使用。
}//智能指针析构的时候递减其引用计数,并决定是否销毁其所拥有的资源

而按照功能上划分,则可以用“COM的智能指针”、“内存管理智能指针”、“IO智能指针”等将智能指针划分为不同类别。

如shared_ptr 和 CComPtr虽然从实现原理上说都是“基于引用技术”的。但却会完成不同的功能,如:shard_ptr在析构时候发现引用计数为0时,会delete掉指针所指的那段内存。而CComPtr则是在析构时简单的调用COM接口的Release()函数。引用计数和COM组件的销毁工作都是由组件自身完成的。明白了这一点,你可能就不会轻易的将一个智能指针简单的用在一个COM接口上了。

本位重点谈论的是COM技术以及其智能指针,所以文章大部分内容只会用CComPtr和_com_ptr_t进行举例。对其他类型的智能指针不加以更为详细的论述,有兴趣的读者可以参看其他资料自行学习。

让我们先来看一下这两COM套指针的概述和,使用的一般方法。

作者“liuchang5的专栏”

相关文章
最新文章
热点推荐