最近在看陈硕的《Linux多线程服务端编程:使用muduo C++网络库》,第一章中重点讲了多线程下指针的处理问题,其中重点是 shared_ptr 与 weak_ptr, 上一篇博客学习了 shared_ptr 的基本用法 ( shared_ptr类模版 ),今天继续学习 weak_ptr ,以下是对 boost::weak_ptr 的中文翻译。
Introduction
weak_ptr 转化到 shared_ptr
weak_ptr 类模版存储了被 shared_ptr 管理的对象的“弱引用”,weak_ptr 能通过使用 shared_ptr 的构造函数 或者成员函数 转化到 shared_ptr。当最后一个指向对象的 shared_ptr 被销毁,对象会被销毁。weak_ptr 的对象被销毁后,试图从 weak_ptr 获得 shared_ptr 将失败,并且构造函数会抛出一个类型为 boost::bad_weak_ptr 的异常,weak_ptr::lock 将返回一个空的 shared_ptr。(?)
标准库
每一个 weak_ptr 都能拷贝构造和赋值,因而能用于标准库容器。另外,还有对比操作符,使得 weak_ptr 能用于标准库的关联容器。
操作
weak_ptr 操作符不抛出异常。
类模版使用 T 作为参数,T 为指向的对象类型。
与 shared_ptr 对比,weak_ptr 提供了非常有限的部分操作,因为在多线程程序里使用它存储的指针式通常是危险的,甚至在单线程中有时也不安全(也就是说,它会引起无定义的行为)。假设 weak_ptr 拥有一个 get 函数能够返回对象指针,如下面错误的代码:1
2
3
4
5
6
7
8
9shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// some time later
if(int * r = q.get())
{
// use *r
}
想象如果在 if 后,在 r 被使用前,另外一个线程运行到了语句 p.reset(),那么 r 现在就成了空悬指针。
空悬指针(dangling pointer)指向已经销毁的对象或已经回收的地址,野指针(wild pointer)指的是 未经初始化的指针(http://en.wikipedia.org/wiki/Dangling_pointer)。
这个问题的解决办法是从 q 创建一个临时的 shared_ptr :1
2
3
4
5
6
7
8
9shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// some time later
if(shared_ptr<int> r = q.lock())
{
// use *r
}
那么现在 r 就有了一个 q 指向对象的引用。即使 p.reset()在另外一个线程被执行,这个对象仍然会存活,直到 r 离开了作用范围或者重新被 reset 了,通过获得对象的 shared_ptr,我们能够有效地锁定它防止销毁。
Synopsis
1 | namespace boost { |
Members
element_type
1 | typedef T element_type; |
提供模版参数 T 的类型
构造函数
1 | weak_ptr(); |
效果:构建一个空的 weak_ptr 。
后置条件:use_count() == 0。
抛出:无。
1 | template<class Y> weak_ptr(shared_ptr<Y> const & r); |
效果:如果 r 是空的,构造一个空的 weak_ptr;否则,构造一个 weak_ptr 与 r 共享所有权,同时存储一份 r 中的指针的拷贝。
后置条件:use_count() == r.use_count()。
抛出:无。
析构函数
1 | ~weak_ptr(); |
效果:销毁这个 weak_ptr,但是对它保存的指针指向的对象无影响。
抛出:无。
赋值函数
1 | weak_ptr & operator=(weak_ptr const & r); |
效果:等同于 weak_ptr(r).swap(*this)。
抛出:无。
use_count
1 | long use_count() const; |
返回:如果*this为空,0;否则,与 weak_ptr 所共享所有权的 shared_ptr 的数目。
抛出:无。
注意:use_count() 不是高效的,只是用来调试和测试。
expired
1 | bool expired() const; |
返回:use_count() == 0。
抛出:无。
注意:expired() 比 use_count() 快。
lock
1 | shared_ptr<T> lock() const; |
返回:expired() ? shared_ptr< T >() : shared_ptr< T >(*this)。
reset
1 | void reset(); |
效果:等价于 weak_ptr().swap(*this)。
swap
1 | void swap(weak_ptr & b); |
效果:交换两个智能指针的内容。
抛出:无。