boost::intrusive_ptr一種「侵入式」的引用計數指針,它實際並不提供引用計數功能,而是要求被存儲的對象本身實現引用計數功能,並提供intrusive_ptr_add_ref和intrusive_ptr_release函數接口供boost::intrusive_ptr調用。html
下面經過一個具體的例子來講明boost::intrusive_ptr的用法,首先實現一個基類intrusive_ptr_base,定義intrusive_ptr_add_ref和intrusive_ptr_release函數來提供引用計數功能。ios
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
/**
* intrusive_ptr_base基類,提供intrusive_ptr_add_ref()和intrusive_ptr_release()函數來提供引用計數功能;
* 使用boost::intrusive_ptr指針存儲的用戶類類型必須繼承自intrusive_ptr_base基類。
*/
#include <ostream>
#include <boost/checked_delete.hpp>
#include <boost/detail/atomic_count.hpp>
template
<
class
T>
class
intrusive_ptr_base {
public
:
/**
* 缺省構造函數
*/
intrusive_ptr_base(): ref_count(0) {
std::cout <<
" Default constructor "
<< std::endl;
}
/**
* 不容許拷貝構造,只能使用intrusive_ptr來構造另外一個intrusive_ptr
*/
intrusive_ptr_base(intrusive_ptr_base<T>
const
&): ref_count(0) {
std::cout <<
" Copy constructor..."
<< std::endl;
}
/**
* 不容許進行賦值操做
*/
intrusive_ptr_base& operator=(intrusive_ptr_base
const
& rhs) {
std::cout <<
" Assignment operator..."
<< std::endl;
return
*
this
;
}
/**
* 遞增引用計數(放到基類中以便compiler能找到,不然須要放到boost名字空間中)
*/
friend
void
intrusive_ptr_add_ref(intrusive_ptr_base<T>
const
* s) {
std::cout <<
" intrusive_ptr_add_ref..."
<< std::endl;
assert
(s->ref_count >= 0);
assert
(s != 0);
++s->ref_count;
}
/**
* 遞減引用計數
*/
friend
void
intrusive_ptr_release(intrusive_ptr_base<T>
const
* s) {
std::cout <<
" intrusive_ptr_release..."
<< std::endl;
assert
(s->ref_count > 0);
assert
(s != 0);
if
(--s->ref_count == 0)
boost::checked_delete(
static_cast
<T
const
*>(s));
//s的實際類型就是T,intrusive_ptr_base<T>爲基類
}
/**
* 相似於shared_from_this()函數
*/
boost::intrusive_ptr<T> self() {
return
boost::intrusive_ptr<T>((T*)
this
);
}
boost::intrusive_ptr<
const
T> self()
const
{
return
boost::intrusive_ptr<
const
T>((T
const
*)
this
);
}
int
refcount()
const
{
return
ref_count;
}
private
:
///should be modifiable even from const intrusive_ptr objects
mutable
boost::detail::atomic_count ref_count;
};
|
用戶類類型須要繼承intrusive_ptr_base基類,以便具備引用計數功能。函數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#include <iostream>
#include <string>
#include <boost/intrusive_ptr.hpp>
#include "intrusive_ptr_base.hpp"
/**
* 用戶類類型繼承自intrusive_ptr_base,該實現方式相似於boost::enable_shared_from_this<Y>
*/
class
Connection :
public
intrusive_ptr_base< Connection > {
public
:
/**
* 構造函數,調用intrusive_ptr_base< Connection >的缺省構造函數來初始化對象的基類部分
*/
Connection(
int
id, std::string tag):
connection_id( id ), connection_tag( tag ) {}
/**
* 拷貝構造函數,只複製自身數據,不能複製引用計數部分
*/
Connection(
const
Connection& rhs):
connection_id( rhs.connection_id ), connection_tag( rhs.connection_tag) {}
/**
* 賦值操做,一樣不能複製引用計數部分
*/
const
Connection operator=(
const
Connection& rhs) {
if
(
this
!= &rhs) {
connection_id = rhs.connection_id;
connection_tag = rhs.connection_tag;
}
return
*
this
;
}
private
:
int
connection_id;
std::string connection_tag;
};
int
main() {
std::cout <<
"Create an intrusive ptr"
<< std::endl;
boost::intrusive_ptr< Connection > con0 (
new
Connection(4,
"sss"
) );
//調用intrusive_ptr_add_ref()遞增引用計數
std::cout <<
"Create an intrusive ptr. Refcount = "
<< con0->refcount() << std::endl;
boost::intrusive_ptr< Connection > con1 (con0);
//調用intrusive_ptr_add_ref()
std::cout <<
"Create an intrusive ptr. Refcount = "
<< con1->refcount() << std::endl;
boost::intrusive_ptr< Connection > con2 = con0;
//調用intrusive_ptr_add_ref()
std::cout <<
"Create an intrusive ptr. Refcount = "
<< con2->refcount() << std::endl;
std::cout <<
"Destroy an intrusive ptr"
<< std::endl;
return
0;
}
|
程序運行輸出:this
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...atom
對比boost::shared_ptrspa
使用boost::shared_ptr用戶類本省不須要具備引用計數功能,而是由boost::shared_ptr來提供;使用boost::shared_ptr的一大陷阱就是用一個raw pointer屢次建立boost::shared_ptr,這將致使該raw pointer被屢次銷燬當boost::shared_ptr析構時。即不能以下使用:指針
那麼爲何一般鼓勵你們使用shared_ptr,而不是intrusive_ptr呢, 在於shared_ptr不是侵入性的,能夠指向任意類型的對象; 而intrusive_ptr所要指向的對象,須要繼承intrusive_ptr_base,即便不須要,引用計數成員也會被建立。code