1. Boost提供六种智能指针:scoped_ptr,scoped_array,shared_ptr,shared_array,weak_ptr,intrusive_ptr,他们都是轻量级的对象,速度和原始指针相差无几,对所有类型T只需要:类型T的析构函数都不能抛异常。
2. scoped_ptr:类似于auto_ptr的智能指针,但是它的所有权更加严格,不能转让,一但它获得对象的管理权,你就无法从那里取回来。并且只在本作用域里使用,不希望转让。提供的操作:
1) reset(T* p = 0):重置scoped_ptr,删除原来保存的指针,再保存新的指针值p。一般情况下reset不应该被调用,因为资源一致应该由scoped_ptr自己自动管理。
2) scoped_ptr不支持比较操作,operator==和operator!=两个操作符都声明为私有。但是支持在bool语境中自动转换成bool值(如if条件表达式),用来测试scoped_ptr是否持有一个有效的指针(非空)。
3) 成员函数swap可以交换两个scoped_ptr保存的原始指针,也可以被boost::swap所利用。
4) 成员函数get,返回scoped_ptr内部保存的原始指针。但是注意不要对这个返回的原始指针做delete操作,否则scoped_ptr析构时会对已经删除的指针再进行删除操作。
5) 与auto_ptr的区别:scoped_ptr的用法与auto_ptr几乎一样,大多数情况下二者可以实现替换,也可以从auto_ptr获得指针管理权(同时auto_ptr失去管理权)。二者同样不能用作容器的元素,但原因不一样:auto_ptr是因为转移语意,scoped_ptr因为不支持拷贝和赋值,不符合容器元素类型的要求。
3. scoped_array(动态数组应该使用std::vector,它提供了比scoped_array更多的灵活性,而只付出了很小的代价,不推荐使用scoped_array):很像scoped_ptr,他包装了new[]操作符在堆上分配的动态数组。接口几乎与scoped_ptr是相同的,主要特点如下:
1) 构造函数接受的指针p必须是new[]的结果,而不能是new表达式的结果;
2) 没有*, ->操作符重载,因为scoped_ptr持有的不是一个普通指针;
3) 析构函数使用delete[]释放资源,而不是delete;
4) 提供operator[]操作符重载,像普通数组一样用下标访问元素;
5) 没有begin(), end()等类似于容器的迭代器操作函数。
4. shared_ptr实现的是引用计数型智能指针。提供的操作:
1) 重载了*, ->操作符,提供隐式bool类型转换以判断指针的有效性,get()可以得到原始指针,并且没有提供指针算术操作;
2) 多种形式的构造函数;(其中还可以定制删除器);
3) reset将引用计数器减1,同时管理参数中的另一个指针;
4) 两个专门的函数检查引用计数:unique()在shared_ptr是指针的唯一所有者返回true和use_count()返回当前指针的引用计数。use_count()应该仅仅用于测试或调试,不提供高效操作;
5) 支持类型转换:static_pointer_cast,const_pointer_cast,dynamic_pointer_cast,都是返回转型后的shared_ptr;
6) 支持流输出符operator<<,输出内部指针值。
5. <boost/make_shared.hpp>提供了一个自由工厂函数make_shared<T>(),来消除显式new调用:shared_ptr<string>sp = make_shared<string>(“hello”);
6. shared_ptr应用于标准容器,一种是将容器作为shared_ptr管理的对象,如shared_ptr<list<T>>,使容器被安全地共享;另一种用法是将shared_ptr作为容器的元素,如vector<shared_ptr<T> >,shared_ptr支持拷贝和比较操作,符合标准容器对元素的要求。
7. shared_ptr可以指定删除器d,告诉shared_ptr在析构时不是使用delete来操作指针p,而是用d来操作,即把deletep换成d(p)。对删除器的要求是必须是可拷贝的,行为必须也像delete那样,不能抛出异常。
8. shared_array类似于shared_ptr,包装了new[]操作符在堆上分配的动态数组。shared_array多数情况下可以用shared_ptr<std::vector<>>或std::vector<shared_ptr>来代替。
9. weak_ptr是为配合shared_ptr而引入的一种智能指针,不具有普通指针的行为,最大的作用就是协助shared_ptr工作,像旁观者那样观测资源的使用情况。特点:
1) weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加;析构也不会导致引用引用计数减少,它只是一个静静的观察者;
2) use_count和expired观测资源的引用计数,expired等价于use_count()== 0,表示观测资源已经不复存在;
3) 没有重载operator*和->,这是特意的,不共享指针,不能操作资源,这也是“弱”的原因;
4) 成员函数lock()从观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。当expired()== true时,lock()函数将返回一个存储空指针的shared_ptr。
10. 获得this的shared_ptr:weak_ptr的一个重要用途就是获得this指针的shared_ptr,使对象自己能够生产shared_ptr管理自己;对象使用weak_ptr观测this指针,这并不影响引用计数,在需要的时候就调用lock()函数,返回一个符合要求的shared_ptr共外界使用。这个解决方案被实现为一个惯用法,在头文件<boost/enable_shared_from_this.hpp>定义了一个助手类enable_shared_from_this<T>,它的声明摘要如下:
template<classT>
class enable_shared_from_this
{
public:
shared_ptr<T> shared_from_this();
}
使用的时候只需要让像被shared_ptr管理的类从它继承即可,成员函数shared_from_this()会返回this的shared_ptr.例如:
#include <boost/make_shared.hpp>
#include <boost/enable_shared_from_this.hpp>
using namespace boost;
using namespace std;
class self_shared: public enable_shared_from_this<self_shared>
{
public:
self_shared(int n):x(n){}
int x;
void print()
{cout<<" self_shared:"<<x<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<self_shared> sp = make_shared<self_shared>(314);
sp->print();
shared_ptr<self_shared> p = sp->shared_from_this();
p->x = 1000;
p->print();
return 0;
}
注意:千万不能从一个普通对象(非shared_ptr)使用shared_from_this()获去shared_ptr,例如:
self_sharedss;
shared_ptr<self_shared> p = ss.shared_from_this();//错误!
在运行时会导致shared_ptr析构时企图删除一个栈上分配的对象,发生未定义行为。