boost::intrusive_ptr一种“侵入式”的引用计数指针,它实际并不提供引用计数功能,而是要求被存储的对象自己实现引用计数功能,并提供intrusive_ptr_add_ref和intrusive_ptr_release函数接口供boost::intrusive_ptr调用。
下面通过一个具体的例子来说明boost::intrusive_ptr的用法,首先实现一个基类intrusive_ptr_base,定义intrusive_ptr_add_ref和intrusive_ptr_release函数来提供引用计数功能。
06 | #include <boost/checked_delete.hpp> |
07 | #include <boost/detail/atomic_count.hpp> |
11 | class intrusive_ptr_base { |
16 | intrusive_ptr_base(): ref_count(0) { |
17 | std::cout << " Default constructor " << std::endl; |
23 | intrusive_ptr_base(intrusive_ptr_base<T> const &): ref_count(0) { |
24 | std::cout << " Copy constructor..." << std::endl; |
30 | intrusive_ptr_base& operator=(intrusive_ptr_base const & rhs) { |
31 | std::cout << " Assignment operator..." << std::endl; |
38 | friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const * s) { |
39 | std::cout << " intrusive_ptr_add_ref..." << std::endl; |
40 | assert (s->ref_count >= 0); |
48 | friend void intrusive_ptr_release(intrusive_ptr_base<T> const * s) { |
49 | std::cout << " intrusive_ptr_release..." << std::endl; |
50 | assert (s->ref_count > 0); |
52 | if (--s->ref_count == 0) |
53 | boost::checked_delete( static_cast <T const *>(s)); |
59 | boost::intrusive_ptr<T> self() { |
60 | return boost::intrusive_ptr<T>((T*) this ); |
63 | boost::intrusive_ptr< const T> self() const { |
64 | return boost::intrusive_ptr< const T>((T const *) this ); |
67 | int refcount() const { |
73 | mutable boost::detail::atomic_count ref_count; |
用户类类型需要继承intrusive_ptr_base基类,以便具有引用计数功能。
03 | #include <boost/intrusive_ptr.hpp> |
04 | #include "intrusive_ptr_base.hpp" |
09 | class Connection : public intrusive_ptr_base< Connection > { |
14 | Connection( int id, std::string tag): |
15 | connection_id( id ), connection_tag( tag ) {} |
20 | Connection( const Connection& rhs): |
21 | connection_id( rhs.connection_id ), connection_tag( rhs.connection_tag) {} |
26 | const Connection operator=( const Connection& rhs) { |
28 | connection_id = rhs.connection_id; |
29 | connection_tag = rhs.connection_tag; |
37 | std::string connection_tag; |
41 | std::cout << "Create an intrusive ptr" << std::endl; |
42 | boost::intrusive_ptr< Connection > con0 ( new Connection(4, "sss" ) ); |
43 | std::cout << "Create an intrusive ptr. Refcount = " << con0->refcount() << std::endl; |
45 | boost::intrusive_ptr< Connection > con1 (con0); |
46 | std::cout << "Create an intrusive ptr. Refcount = " << con1->refcount() << std::endl; |
47 | boost::intrusive_ptr< Connection > con2 = con0; |
48 | std::cout << "Create an intrusive ptr. Refcount = " << con2->refcount() << std::endl; |
50 | std::cout << "Destroy an intrusive ptr" << std::endl; |
程序运行输出:
Create an intrusive ptr
Default constructor
intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 1
intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 2
intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 3
Destroy an intrusive ptr
intrusive_ptr_release...
intrusive_ptr_release...
intrusive_ptr_release...
对比boost::shared_ptr
使用boost::shared_ptr用户类本省不需要具有引用计数功能,而是由boost::shared_ptr来提供;使用boost::shared_ptr的一大陷阱就是用一个raw pointer多次创建boost::shared_ptr,这将导致该raw pointer被多次销毁当boost::shared_ptr析构时。即不能如下使用:
int *a = new int(5);
boost::shared_ptr ptr1(a);
boost::shared_ptr ptr2(a); //错误!
boost::intrusive_ptr完全具备boost::shared_ptr的功能,且不存在shared_ptr的问题,即可以利用raw pointer创建多个intrusive _ptr,其原因就在于引用计数的
ref_count对象,shared_ptr是放在
shared_ptr结构里,
而目标对象T通过继承
intrusive_ptr_base将引用计数作为T对象的内部成员变量,就不会出现同一个对象有两个引用计数器的情况出现。
那么为什么通常鼓励大家使用shared_ptr,而不是intrusive_ptr呢, 在于shared_ptr不是侵入性的,可以指向任意类型的对象; 而intrusive_ptr所要指向的对象,需要继承intrusive_ptr_base,即使不需要,引用计数成员也会被创建。
结论:如果创建新类且需要进行传递,则
继承
intrusive_ptr_base,使用intrusive_ptr。
原文地址:
boost intrusive_ptr原理(兼对比shared_ptr)
boost intrusive_ptr