TAG:
//前半部部分是转的,
最近用到boost的intrusive_ptr,看了一下其实现发现与最初的想象不同,于是认真看了一下,发现其实现非常巧妙。智能指针思想很简单,但实现时需要思考一下,否则容易出bug。比如说下面这段代码:
typedef boost::intrusive_ptr FilePtr;
File* f = new File;
FilePtr old(f);
FilePtr new_(f);
old = new File;
old = new_;
old = NULL;
这里要考虑到:1)当intrusive_ptr包含的是NULL时,不可以对其做操作; 2)当新值与旧值不同时,需要将旧值引用计数减一,而将新值的引用计数加一; 3) 当新值与旧值相同时,引用计数不表; 上面的繁杂的判定被boost很漂亮的实现,其思想是: 1)不对NULL指针处理; 2)永远把新值的引用计数加一,把旧的引用计数减一; 第二步boost利用临时变量的构造函数和析构函数,通过交换指针实现。代码如下: intrusive_ptr & operator=(intrusive_ptr const & rhs) { this_type(rhs).swap(*this); return *this; } intrusive_ptr( T * p, bool add_ref = true ): px( p ) { if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); } intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) { if( px != 0 ) intrusive_ptr_add_ref( px ); } ~intrusive_ptr() { if( px != 0 ) intrusive_ptr_release( px ); } void swap(intrusive_ptr & rhs) { T * tmp = px; px = rhs.px; rhs.px = tmp; } =================举例 T * const ptrT1 = new T(“t1”); T * const ptrT2= new T(“t2”); //t1和t2的ref_count均为0 intrusive_ptr A(ptrT1);//t1的ref_count +1 intrusive_ptr C(ptrT1);//A和C指向同一对象t1,ref_count 为2 intrusive_ptr B(ptrT2);//B指向对象t2,ref_count 为1 A = B;//A指向t2,t2的引用计数+1;而A原来指向的对象t1的引用计数-1 ===================分析 intrusive_ptr & operator=(intrusive_ptr const & rhs) { this_type(rhs).swap(*this); return *this; } 等价代码 { boost::intrusive_ptr Tmp(B) Tmp.swap(A); } 表示intrusive_ptr指针B(内部的指针)指向的对象,b表示该对象的ref_count值
* 基于B生成一个临时的intrusive_ptr Tmp,这样就保证了新值()的引用计数被加一;
(junanhonglei)* 接着,在swap中将A与Tmp所指向的对象交换,这样A指向了原来B指向的对象 * 在临时对象Tmp被销毁时自动将A原来指向的对象 使用智能指针需要注意的事项:
intrusive_ptr A(&t) ;//error,
void test()
{
foo(boost::shared_ptr(new implementation()),g());
}
正确的用法为:void test()
{
boost::shared_ptr sp (new implementation());
foo(sp,g());
}
int *a = new int(5) ;
boost::smart_ptr ptr1(a);
boost::smart_ptr ptr2(a);//error,
boost::smart_ptr ptr2(ptr1);//OK
|