boost 库 内存管理 weak_ptr intrusive_ptr 4

weak_ptr

weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为weak_ptr不具有普通指针的行为,没有重载operator*operator->。weak_ptr的最大作用用来协助shared_ptr工作,观测资源的使用情况。

类摘要

weak_ptr类摘要

用法

weak_ptr被设计为与shared_ptr共同工作,可从一个shared_ptr或者weak_ptr对象构造,获得对象的观测权,但weak_ptr没有共享资源,weak_ptr不会引起指针引用计数的增加,weak_ptr析构也不会导致指针引用计数的减少。
weak_ptr成员函数use_count()可以观测资源的引用计数。weak_ptr成员函数expired()的功能等价于use_count()==0,表示观测的资源已经不复存在,但expired的速度更快。
weak_ptr没有重载operator*->,不共享指针,不能操作资源。weak_ptr可以使用成员函数lock()从观测的shared_ptr获得可用的shared_ptr对象,操作资源,当expired()==true时,lock函数返回存储空指针的shared_ptr。

获得this的shared_ptr

weak_ptr的一个重要用途是获得this指针的shared_ptr,使对象自己能够生产shared_ptr管理自己,对象使用weak_ptr观测this指针,在需要的时候调用lock()函数,返回符合要求的shared_ptr供外界使用。

1
2
3
4
5
6
template<class T>
class enable_shared_from_this
{
public:
shared_ptr<T> shared_from_this();
}

想被shared_ptr管理的类从enable_shared_from_this继承,成员函数shared_from_this()返回this的shared_ptr。不能从普通对象使用shared_from_this()获取shared_ptr,否则运行时会导致shared_ptr析构时企图删除一个栈上分配的对象。

intrusive_ptr

intrusive_ptr是侵入式的引用计数型指针,应用于:

  • 对内存占用的要求非常严格,要求必须与原始指针一样。
  • 现存代码已经有了引用计数机制管理的对象。

Boost库不推荐使用intrusive_ptr,shared_ptr足够啦。

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
class H : public boost::enable_shared_from_this<H>
{
public:
H(int _n) : n(_n)
{
cout<<"H ctor"<<endl;
}
void print()
{
cout<<"H n:"<<n<<endl;
}
int n;
};

void TestWeakPtr()
{
boost::shared_ptr<int> sp1(new int(10));
cout<<"sp1 use_count:"<<sp1.use_count()<<endl;
boost::weak_ptr<int> wp1(sp1);
cout<<"sp1 use_count:"<<sp1.use_count()<<endl;
cout<<"wp1 use_count:"<<wp1.use_count()<<endl;

if(!wp1.expired())
{
boost::shared_ptr<int> sp2 = wp1.lock();
cout<<"sp1 use_count:"<<sp1.use_count()<<endl;
cout<<"sp2 use_count:"<<sp2.use_count()<<endl;
}
cout<<"sp1 use_count:"<<sp1.use_count()<<endl;
sp1.reset();

cout<<"wp1 use_count:"<<wp1.use_count()<<endl;

boost::shared_ptr<H> sh = boost::make_shared<H>(314);
sh->print();
boost::shared_ptr<H> sh2 = sh->shared_from_this();
sh->n = 1000;
sh2->print();
sh->print();
}