1.初识weak_ptr
weak_ptr是为配合shared_ ptr而引入的一种智能指针,它更像是shared_ptr的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和->. 它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况.
2.类摘要
weak_ptr的类摘要如下:
template <class T>
class weak_ptr
{
public:
weak_ptr(); // 构造函数
template<class Y> weak_ptr(shared_ptr<Y> const &r);
weak_ptr(weak_ptr const & r); // 拷贝构造函数
~weak_ptr(); // 析构函数
weak_ptr& operator=(weak_ptr const &r); // 赋值操作符重载
long use_count() const; // 引用计数
bool expired() const; // 是否为失效指针
bool empty() const; // 是否为空指针,非标准
shared_ptr<T> lock() const; // 获取shared_ptr
void reset(); // 重置指针
void swap(weak_ptr<T>& b); // 交换指针
};
weak_ptr的接口很小,正如它的名字,它是一个“弱”指针,但它能够完成一些特殊的工作,足以证明它的存在价值.
3.用法
weak_ptr被设计为与shared_ptr协同工作,可以从一个shared _ptr或者另一个weak_ ptr对象构造,获得资源的观测权.但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加.同样,weak _ptr析构时也不会导致引用计数减少,它只是一个静静的观察者.
使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count ()==0,但更快,表示被观测的资源(也就是被shared ptr管理的资源)已经不复存在.
weak_ptr没有重载operator*和->,这是特意的,因为它不共享指针,不能操作资源,这正是它“弱”的原因. 但它可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared _ptr对象,把弱关系转换为强关系,从而操作资源. 但当expired ()==true的时候,lock ()函数将返回一个存储空指针的shared_ptr.
下面的代码示范了weak_ptr的用法:
g++ 004-weak-ptr-001.cpp -std=c++11
#include <memory>
#include <assert.h>
using namespace std;
int main()
{
shared_ptr<int> sp(new int(10)); // 一个shared_ptr
assert(sp.use_count() == 1);
weak_ptr<int> wp(sp); // 从shared_ptr创建weak_ptr
assert(wp.use_count() == 1); // weak_ptr不影响引用计数
assert(!wp.expired());
if(!wp.expired()) // 判断weak_ptr观察的对象是否失效
{
shared_ptr<int> sp2 = wp.lock(); // 获得一个shared_ptr
*sp2 = 100;
assert(wp.use_count() == 2);
} // 退出作用域,sp2自动析构,引用计数减1
assert(wp.use_count() == 1);
sp.reset(); // shared_ptr失效
assert(wp.expired());
assert(!wp.lock()); // weak_ptr将获得一个空指针
}
4.enable_shared_from_this
weak_ptr的一个重要用途是获得this指针的 shared_ptr,使对象自己能够生产shared_ptr管理自己:对象使用weak_ptr观测this指针,这并不影响引用计数,在需要的时候就调用lock ()函数,返回一个符合要求的shared_ptr供外界使用:
这个解决方案被实现为一个惯用法,在头文件<boost/enable_shared_from_this.hpp>定义了一个助手类enable_shared_from_this<T>,它的声明摘要如下:
template<class T>
class enable_shared_from_this
{
public:
shared_ptr<T> shared_from_this();
}
使用的时候只需要让想被shared_ptr 管理的类从它派生即可,成员函数shared_from_this ()会返回this的shared_ptr。例如: