使用智能指针是C++中常用的管理内存的方式。关于智能指针的设计,各路C++高手也是各展神通。
在1994年. Greg Colvin向C++标准委员会提出了自己设计的智能指针:auto_ptr和counted_ptr。auto_ptr实现基本的RAII管理,不可复制;counted_ptr采用引用计数实现了一个可复制的智能指针。两者用于不同的场合。
但是标准委员会最终只通过了auto_ptr,并且对auto_ptr加入了一个古怪的“所有权转移”语义。后来auto_ptr和counted_ptr进入了Boost C++ 库,改名为scoped_ptr和shared_ptr。
std::auto_ptr只所以设计为可拷贝的,也许是出于以下考虑,比如下例函数:
void f1(object* ptr);
object* f2();
f1中的参数所指向的对象应该由谁来删除呢?调用者还是被调用者?如果不看程序文档的话,无法知道这一点。f2函数也存在同样的问题。
用auto_ptr可以消除这种歧义性:
void f1(auto_ptr<object> ptr);
auto_ptr<object> f2();
尽管如此,auto_ptr的“所有权转移”语义还是会带来副作用,因为会修改原值的常量拷贝违背了一般的设计原则,它也许会在你意想不到的情况下就把对象转移了。它也不能用于标准容器中。
所以auto_ptr在新的标准库已经不再推荐使用。取而代之的是unique_ptr。unique_ptr与auto_ptr类似,但限制了auto_ptr的拷贝行为。同时,像上面举的例子一样,unique_ptr可以作为函数的参数和返回值使用。这是因为C++增加了一个新的特征:右值引用。
shared_ptr也进入了标准库。对于引用计数的智能指针而言,循环引用是一个大问题。标准库为此把shared_ptr定义为强引用指针,它还实现了一个弱引用指针weak_ptr。显然,标准库并没有从根本上解决循环引用的问题,它把这个问题交给了程序员。在一个简单的系统中,你可以区分使用shared_ptr和weak_ptr,以此来避免出现循环引用。但是在一个大的对象系统中,有时还是容易出错。循环引用的问题,严重减弱了shared_ptr的可用性。
那么能不能自动检测是否出现循环引用呢?事实上,对于shared_ptr这种使用非侵入式策略实现的智能指针,是很难实现自动检测的。但是如果采用侵入式设计,我们可以引入一些接口,来解决这个问题。循环引用的检测,实际上是图论中的回路检测问题。
本文由eXile 原创,转载请表明原贴地址。 http://www.cppblog.com/eXile/。