最近用到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值
公式 A B Tmp 等价公式
* * NULL
this_type(rhs) * * boost::intrusive_ptr Tmp(B)
.swap(*this) * * * Tmp.swap(A)
this_type(rhs).~intrusive_ptr() * * * Tmp析构
* 基于B生成一个临时的intrusive_ptr Tmp,这样就保证了新值( )的引用计数被加一;
* 接着,在swap中将A与Tmp所指向的对象交换,这样A指向了原来B指向的对象
* 在临时对象Tmp被销毁时自动将A原来指向的对象
使用智能指针需要注意的事项:
不能指向Stack memory对象(shared_ptr,auto_ptr,intrusive_ptr均不可以)
T t;
intrusive_ptr A(&t) ;//error,
不要构造一个临时的shared_ptr作为函数的参数。
如下列代码则可能导致内存泄漏:
void test()
{
foo(boost::shared_ptr(new implementation()),g());
}
正确的用法为:
void test()
{
boost::shared_ptr sp (new implementation());
foo(sp,g());
}
一个raw pointer只能创建一个shared_ptr,否则raw pointer指向的对象会被析构多次
即不能如下使用:
int *a = new int(5) ;
boost::smart_ptr ptr1(a);
boost::smart_ptr ptr2(a);//error,
boost::smart_ptr ptr2(ptr1);//OK
相关视频
相关阅读 lol源代码星妈多少钱 lol源代码索拉卡视频lol源代码皮肤冰霜女巫什么时候出 lol源代码皮肤丽桑卓视频预览雅虎计划在开源社区发布非核心技术源代码将pdf文件转成图片并删除java源代码一个Asp.Net验证码源代码经典php实现大文件上传源代码html源代码攻防战如何获取cookie的源代码
热门文章 Wordpress本地安装教程dx1.5如何设置二级域名
最新文章
hbuilder有哪些快捷键Wordpress本地安装教程
Wordpress本地安装教程expression web 4文档乱码解决方法dz 2.5“收藏本版”关闭小对话框无法关闭解在制作安装软件之前,您必须先将易语言存盘,
人气排行 如何使用multipart/form-data格式上传文件Photoshop PS图层混合模式详解(非常详细)ISAPI_Rewrite3使用教程网站里添加收藏和设为首页代码桌面快捷方式图标不见了C#获取执行程序所在的当前路径的方法详解(XMLHttpRequest)进行跨域请求方法如何用远程桌面连接进行传输文件
查看所有0条评论>>