发布时间:2014-6-4 12:09
分类名称:Boost
auto_ptr | scoped_ptr | shared_ptr |
无引用计数 | 无引用计数 | 有引用计数 |
不同auto_ptr引用一个指针,导致多次析构而崩溃
int* p = new int(0); auto_ptr<int> ap1(p); auto_ptr<int> ap2(p);
一个指针被多个auto_ptr引用,导致多次析构,程序崩溃。 | 同auto_ptr 预防的方式为: 将new 操作直接作为参数传入,等于建立一个临时变量: scopted_ptr<int> sp(new int(0)); 这样,从语言层以后就无法再次引用。
由于构造函数explicit关键字的限制,这些智能指针只能在定义的时候初始化,以后不能被再次赋值其它指针,如: CTest *p = new CTest; std::auto_ptr<CTest> ap; ap = p; // 错误,编译器报错 | 同样也是无法预防,但是在Boost里,有预防此情况的调试机制: 如果定义了宏BOOST_SP_ENABLE_DEBUG_HOOKS, 当出现此种情况时,第二次的引用会弹出一个assert调试框。其代码实现在: libs\smart_ptr\src\sp_debug_hooks.cpp中。调试机制提前预防了多次析构的问题,所以在Debug的状态,打开此机制。此调试机制适应于boost中所有智能指针(smart_ptr) |
无法处理动态数组 int* pa = new int[10]; auto_ptr<int> ap(pa); 因为auto_ptr析构删除指针使用的的是delete,而不是delete[],所以这种用法不正确,程序的运行结果未定。 | scoped_array可以来处理动态数组。 动态数组最好使用vector代替。 | shared_array来处理动态数组。 |
独占,不共享,所有权转移 因为没有引用计数,所以无法实现多个auto_ptr共享一个指针的目的。所以拷贝和复制操作,需要特殊处理,保证拷贝后,被拷贝的auto_ptr不再有原指针的所有权。(所有权转移)
使用没有原指针所有权auto_ptr是很危险的,就如同在操作一个空指针一样。如: int* p = new int(0); auto_ptr<int> ap1(p); auto_ptr<int> ap2 = ap1; cout<<*ap1; //错误,此时ap1只剩一个null指针在手了
更加隐蔽的: void f(auto_ptr<int> ap){cout<<*ap;} auto_ptr<int> ap1(new int(0)); f(ap1); cout<<*ap1; //错误,经过f(ap1)函数调用,ap1已经不再拥有任何对象了。
独占的特性导致了它的危险性。 | 独占,不共享,不过无法转移: 不能转移的技术: 将能拷贝和赋值构造函数都声明为私有。 private: scoped_ptr(scoped_ptr const &); scoped_ptr & operator= (scoped_ptr const &); void operator==( scoped_ptr const& ) const; void operator!=( scoped_ptr const& ) const;
此接口保证功能最小,主要起自动释放的作用。 | 共享,通过引用计数来维护指针
由于有引用计数,多个share_ptr可以引用一个指针。使用起来,和实际的指针基本上是一模一样。 |
不具有值语义(value semantic) 因为具有所有权转移特性 不能被用在STL标准容器中 | 不具有值语义(value semantic) 因为不支持拷贝,赋值等操作 不能被用在STL标准容器中 | 就有值语意 可以用在容器中。 |
辅助函数 get函数,获取原始指针。 release 函数,转移所有权(不释放,只是清零) reset函数,用来接收所有权,如果接收所有权的auto_ptr如果已经拥有某对象, 必须先释放该对象。 operator bool() | 辅助函数 get函数,获取原始指针。 reset函数,用来接收所有权,如果接收所有权的auto_ptr如果已经拥有某对象, 必须先释放该对象。
| 辅助函数 reset,引用计数减1,停止对指针共享,如果引用计数为零,释放对象 get,获取原始指针 unique,判断引用计数是否为1. use_count,获取当前引用计数。 operator bool() make_shared,工厂函数
转换辅助函数 static_pointer_cast dynamic_pointer_cast const_pointer_cast
定制删除器 shared_ptr(Y *p, D d),管理任何资源。 |
需要注意的地方颇多,稍不注意就会发生错误,建议只做自动释放的功能,不要做为函数参数,或者赋值转移等操作 | 相对auto_ptr做了防御编程,但没有完全防止,建议只做自动释放的功能。 | 功能最完善,最像一个正常的指针。需要注意两点:
|