intrusive_ptr使用案例
1 简介Boost::intrusive_ptr
总体上讲:Boost::intrusive_ptr和shared_ptr功能上几乎是一致
,唯一不同的是,计数器递增、递减可以由用户自定义。
// 递增计数器,注意:函数名是内置,必须写这个名字!!!
void intrusive_ptr_add_ref(T *p)
// 递减计数器,注意:函数名是内置,必须写这个名字!!!
void intrusive_ptr_release(T *p)
下面分享下两个小案例
2 Demo1
假定,定义一个count_data,里面有一个计数器m_count。其中这个计数器就相当于shared_ptr的内置计数器,只不过intrusive_ptr可以单独操作。
- 简要实现intrusive_ptr_add_ref和intrusive_ptr_release
- counted_ptr就像shared_ptr一样智能,以至于根据m_count正确的析构对象
- counted_ptr weak_p(p.get(), false);,false相当于是weak_ptr(是一个观察者,不会增加引用计数),默认是shared_ptr
#include <iostream>
#include <boost/smart_ptr.hpp>
struct count_data
{
int m_count = 0;
// other funtion or data
};
// 下面两个函数是内置的,只需要填写计算变量++/--
void intrusive_ptr_add_ref(count_data *p) {
++p->m_count;
}
void intrusive_ptr_release(count_data *p) {
if (--p->m_count == 0)
delete p;
}
int main(int argc, char *argv[])
{
typedef boost::intrusive_ptr<count_data> counted_ptr;
counted_ptr p(new count_data);
assert(p);
assert(p->m_count == 1); // p拥有
counted_ptr p2(p);
assert(p->m_count == 2); // 指针拷贝构造,p和p2同时拥有
counted_ptr weak_p(p.get(), false); // 值为false,相当于weak_ptr,只是一个观察者,不会增加引用计数
assert(weak_p->m_count == 2); // p和p2同时拥有,weak_p观察者
p2.reset(); // 将p2置零
assert(!p2);
assert(p->m_count == 1); // p拥有,weak_p观察者
}
3 Demo 2
目的: 更加简化计数管理,直接继承intrusive_ref_counter即可
下面的代码并没有使用intrusive_ptr_add_ref和intrusive_ptr_release,同时也不需要计数器m_count,更加像shared_ptr了。
- 直接继承intrusive_ref_counter,之类可以得到计算能力
- 头文件 <boost/smart_ptr/intrusive_ref_counter.hpp>
#include <iostream>
#include <boost/smart_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
// Method2
struct count_data2 : public boost::intrusive_ref_counter<count_data2>
{
/* data */
};
int main(int argc, char *argv[])
{
typedef boost::intrusive_ptr<count_data2> counted_ptr2;
counted_ptr2 p(new count_data2);
assert(p);
assert(p->use_count() == 1); // p拥有,正确析构
}
4 内部部分API简要的实现
可以看出,
- intrusive_ptr在构造,析构调用intrusive_ptr_add_ref和intrusive_ptr_release进行计数管理
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 );
}
- reset相当于置零,其中this_type是intrusive_ptr<>,构造一个空的intrusive_ptr再和自己交换,当然也就置0了哈。
void reset()
{
// 等效于intrusive_ptr<>().swap(*this)
this_type().swap( *this );
}
默认构造一个空的,px是指针,pn是计数器
BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
{
}
更加详细的代码。可以参考Boost的源码
5 有何作用?
既然intrusive_ptr和shared_ptr如此相像,那么intrusive_ptr有什么作用呢?
答:如果你的类中有了计数管理器,可以考虑intrusive_ptr,否则都用shared_ptr,因为shared_ptr不需要增加代码,灵活性很高。