boost::shared_ptr文档翻译
shared_ptr: 共享所有权
描述
模版类 shared_ptr 存储动态构造对象的指针,通常是由C++ new语句完成的。这个对象指针在最后一个持有指针所有权的shared_ptr被销毁或者重置(reset)的时候,指针被delete。
例1: 使用 shared_ptr
shared_pt<X> p1( new X );
shared_ptr<void> p2( new int(5) );
shared_ptr 会使用构造时的原始类型从而正确的删除指针,不管模版类型是什么。在例1,p2被销毁或者重置(reset)的时候,会调用delete操作法删除int*类型指针,即使模版类型是void,shared_ptr存储的也是void*类型的指针。
shared_ptr 满足C++标准库拷贝构造、移动构造、拷贝赋值和移动赋值的需求,也可以用在C++标准库容器上。也提供了比较操作,所以shared_ptr也可以用在C++标准库关联容器上。
由于shared_ptr实现上采用了引用计数,循环引用将导致资源不能正确的回收。例如shared_ptr对象A,不管是直接或间接返回对象A,A的引用计数会变成2。析构对象A引用计数变成1,不会去释放资源。使用 weak_ptr 可以避免循环引用。
shared_ptr类的模版参数T,是指向的对象的类型,其大部分成员函数不要求模版参数T。可以是不完整的类型或 void 类型。构造函数和reset需要显示地指出新的参数类型。
当 T* 可以隐式转换成 U* 时,shared_ptr<T>也可以隐式转换成shared_ptr<U>。尤其是shared_ptr<T>隐式转换成shared_ptr<T const>、shared_ptr<U>(类型U是类型T的可访问基类)、shared_ptr<void>。
shared_ptr 在C++11标准上被命名为 std::shared_ptr。
随着boost 1.53版本,shared_ptr 可以存储动态分配的数组,可以使用数组类型(T[]/T[N])作为模版参数。使用不定数量当数组T[]和一定数量的数组T[N],几乎是没有区别的;后者能够使用operator[]对索引(index)执行范围检查。
例2:使用数组类型的shared_ptr
shared_ptr<double[1024]> p1( new double[1024] );
shared_ptr<double[]> p2( new double[] );
最佳实践
一个简单的消除内存泄漏的可能的指导是总是使用命名的智能指针变量去存储new操作返回的指针对象。每个使用new的代码都应该是下面这种类型:
shared_ptr p(new Y);
当然可以使用另一种智能指针类型代替上面的shared_ptr,T和Y可以是相同的类型,h或传递参数给Y的构造函数也是可以的。
如果你遵守这个规则,很显然你不需要显示delete语句,try/catch结构也会很少。
避免使用不命名的shared_ptr临时变量去保存类型,要了解为什么这是危险的,请考虑这个例子:
例3:使用shared_ptr的异常安全和不安全
void f(shared_ptr<int>, int);
int g();
void ok()
{
shared_ptr<int> p(new int(2));
f(p, g());
}
void bad()
{
f(shared_ptr<int>(new int(2)), g());
}
函数 ok 是正确使用智能指针的方式,而 bad 使用 shared_ptr 临时变量的形式存在内存泄漏的可能。因为函数参数的计算顺序是未知的,可能是先计算 new int(2),然后 g(),如果函数g抛出异常,就不会构造shared_ptr对象。关于这个问题的更多信息可以点击Herb Sutter’s treatment
上述异常安全的问题也可以使用工厂函数(make_shared/allocate_shared),这两个函数定义在<boost/smart_ptr/make_shared.hpp>。这两个工厂函数还能保证效率上的提升。
简介
shared_ptr 定义在 <boost/smart_ptr/shared_ptr.hpp>
namespace boost {
class bad_weak_ptr: public std::exception;
template<class T> class weak_ptr;
template<class T> class shared_ptr {
public:
typedef /*see below*/ element_type;
constexpr shared_ptr() noexcept;
constexpr shared_ptr(std::nullptr_t) noexcept;
template<class Y> explicit shared_ptr(Y * p);
template<class Y, class D> shared_ptr(Y * p, D d);
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
template<class D> shared_ptr(std::nullptr_t p, D d);
template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
~shared_ptr() noexcept;
shared_ptr(shared_ptr const & r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept;
shared_ptr(shared_ptr && r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
template<class Y> shared_ptr(std::auto_ptr<Y> && r);
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
shared_ptr & operator=(shared_ptr const & r) noexcept;
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;
shared_ptr & operator=(shared_ptr const && r) noexcept;
template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r) noexcept;
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
shared_ptr & operator=(std::nullptr_t) noexcept;
void reset() noexcept;
template<class Y> void reset(Y * p);
template<class Y, class D> void reset(Y * p, D d);
template<class Y, class D, class A> void reset(Y * p, D d, A a);
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;
T & operator*() const noexcept; // only valid when T is not an array type
T * operator->() const noexcept; // only valid when T is not an array type
// only valid when T is an array type
element_type & operator[](std::ptrdiff_t i) const noexcept;
element_type * get() const noexcept;
bool unique() const noexcept;
long use_count() const noexcept;
explicit operator bool() const noexcept;
void swap(shared_ptr & b) noexcept;
template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
};
template<class T, class U>
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;
template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;
template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;
template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
template<class T>
typename shared_ptr<T>::element_type *
get_pointer(shared_ptr<T> const & p) noexcept;
template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
template<class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
template<class T, class U>
shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;
template<class E, class T, class Y>
std::basic_ostream<E, T> &
operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
template<class D, class T> D * get_deleter(shared_ptr<T> const & p) noexcept;
template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;
template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;
template<class T>
shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;
template<class T>
void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
template<class T>
void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
template<class T>
shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
template<class T>
shared_ptr<T> atomic_exchange_explicit(
shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
template<class T>
bool atomic_compare_exchange(
shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;
template<class T>
bool atomic_compare_exchange_explicit(
shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;
}
成员函数
- element_type
typedef ... element_type
当T不是数组类型时,element_type是类型T,当T是数组类型(U[]/U[N])时,element_type是类型U。
- default constructor
constexpr shared_ptr() noexcept;
constexpr shared_ptr(std::nullptr_t) noexcept;
构造一个空的shared_ptr,其满足条件
use_count() == 0 && get() == 0
- pointer constructor
template<class Y> explicit shared_ptr(Y* p);
类型Y必须是完整类型。当T是数组类型,表达式delete[] p;当T不是数组类型,表达式delete p必须是符合语法规则、符合定义并不会抛出异常的。当类型T是U[N],Y(*)[N]可以转换成T*;当类型T是U[],Y(*)[]可以转换成T*;除此之外Y*可以转换成T*。
当类型T不是数组类型,构造一个拥有p所有权的shared_ptr。除此之外构造一个拥有数组p所有权的shared_ptr,默认的删除器是delete[] p。
use_count() == 1 && get() == p。如果类型T不是数组类型并且p可以明确的转换成enabled_shared_from_this<V>,p->shared_from_this()返回*this的副本。
内存不足时抛出std::bad_alloc或实现定义的异常。
异常安全,当T是数组类型,构造函数会调用delete[] p;当T不是数组类型,会调用delete p。
note:
p必须是0或者C++ new出来的指针类型。当p是0时,use_count()也是1,并且delete p也是不会报错的。
这个构造函数会用模板记录实际传入的类型,析构函数会delete原始类型,即便T没有虚析构函数或void类型。
- constructors taking a deleter
template<class Y, class D> shared_ptr
(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D> shared_ptr(std::nullptr_t p, D d);
template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
类型D必须是可拷贝构造的。D的构造和析构不能抛出异常。表达式delete p必须是符合语法规则、符合定义并不会抛出异常的。类型A必须是符合C++标准的内存配置器。当类型T是U[N],Y(*)[N]可以转换成T*;当类型T是U[],Y(*)[]可以转换成T*;除此之外Y*可以转换成T*。
构造一个拥有指针p所有权和删除器d的shared_ptr对象。带内存配置器的构造函数使用配置器a分配内存。
use_count() == 1 && get() == p。如果类型T不是数组类型并且p可以明确的转换成enabled_shared_from_this<V>,p->shared_from_this()返回*this的副本。
内存不足时抛出std::bad_alloc或实现定义的异常。
异常抛出时,会调用d(p)。
- copy and converting constructors
shared_ptr(shared_ptr const &r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const &r) noexcept;
Y* 可以隐式转换成 T*。
如果 r 是空shared_ptr,则构造一个空shared_ptr;否则构造一个拥有r所有权的shared_ptr。
get() == r.get() && use_count() == r.use_count()
- move constructors
shared_ptr(shared_ptr const &&r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const &&r) noexcept;
Y* 可以隐式转换成 T*。
移动构造一个shard_ptr.
新构造的shared_ptr接管r管理的内存。如果r是空对象,则r.get() == 0。
- aliasing constructor
template<class Y> shared_ptr(shared_ptr<Y> const &r, element_type *p) noexcept;
构造一个shared_ptr对象,拥有r的所有权并存储指针p。
get() == p && use_count() == r.use_count()。
- aliasing move constructor
template<class Y> shared_ptr(shared_ptr<Y> const &&r, element_type *p) noexcept;
移动构造一个shared_ptr对象,拥有r的所有权并存储指针p。
get() == p && use_count() == r.use_count()。如果r是空对象,r.get() == 0。
- weak_ptr constructor
template<class Y> explicit shared_ptr(weak_ptr<class Y> const& r);
Y* 可以隐式转换成 T*。
构造一个shared_ptr对象,拥有r的所有权并存储r的指针副本。
use_count() == r.use_count()。
当 r.use_count() == 0 时,抛出异常bad_weak_ptr
如果抛出异常,那么构造函数没有起作用。
- auto_ptr constructor
template<class Y> shared_ptr(auto_ptr<class Y> const& r);
template<class Y> shared_ptr(auto_ptr<class Y> const&& r);
Y* 可以隐式转换成 T*。
构造一个shared_ptr对象,存储r.release()
use_count() == 1。
当内存资源不足时,抛出异常std::bad_alloc或实现定义的异常。
如果抛出异常,那么构造函数没有起作用。
- unique_ptr constructor
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
Y* 可以隐式转换成 T*。
- r.get() == 0,相当于构造shared_ptr()
- 删除器D不是引用类型,相当于构造shared_ptr(r.release(), r.get_deleter())
- 否正相当于构造shared_ptr(r.release(), del)。当del是个删除器时,del(p)会被调用
当内存资源不足时,抛出异常std::bad_alloc或实现定义的异常。
如果抛出异常,那么构造函数没有起作用。
- destructor
~shared_ptr() noexcept;
-空shared_ptr,或者use_count() > 1,什么也不做
- use_count() == 1,有删除器d调用d(p),否正调用delete p
- assignment
shared_ptr& operator=(shared_ptr const& r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y> const& r) noexcept;
template<class Y> shared_ptr& operator=(std::auto_ptr<Y> const& r);
相当于 shared_ptr(r).swap(*this)
返回*this
shared_ptr& operator=(shared_ptr && r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y> && r) noexcept;
template<class Y> shared_ptr& operator=(std::auto_ptr<Y> && r);
template<class Y, class D> shared_ptr& operator=(std::unique_ptr<Y, D> && r);
相当于 shared_ptr(std::move(r)).swap(*this)
返回*this
shared_ptr& operator=(std::nullptr_t) noexcept;
相当于 shared_ptr().swap(*this)
返回*this
- reset
void reset() noexcept;
相当于 shared_ptr().swap(*this)
template<class Y> void reset(Y * p);
相当于 shared_ptr(p).swap(*this)
template<class Y, class D> void reset(Y * p, D d);
相当于 shared_ptr(p, d).swap(*this)
template<class Y, class D, class A> void reset(Y * p, D d, A a);
相当于 shared_ptr(p, d, a).swap(*this)
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;
相当于 shared_ptr(r, p).swap(*this)
template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;
相当于 shared_ptr(std::move(r), p).swap(*this)
- indirection
T & operator*() const noexcept;
类型T不是数组类型。get() != 0
返回 *get()
T * operator->() const noexcept;
类型T不是数组类型。get() != 0
返回 get()
element_type & operator[](std::ptrdiff_t i) const noexcept;
类型T是数组类型。get() != 0。如果T是T[U],那么i < N
返回 get()[i]
- get
element_type * get() const noexcept;
返回shared_ptr存储的指针
- unique
bool unique() const noexcept;
返回 use_count() == 1
- use_count
long use_count() const noexcept;
如果存储指针为空返回0,否正返回持有该指针地址的shared_ptr数量
- conversions
explicit operator bool() const noexcept;
返回 get() != 0
- swap
void swap(shared_ptr & b) noexcept;
交换两个智能指针的保存的指针
- owner_before
template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
详见 operator< 的解释
友元函数
- comparison
template<class T, class D> bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
返回 a.get() == b.get()
template<class T, class D> bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
返回 a.get() != b.get()
template<class T> bool operator==(shared_ptr<T> const & a, std::nullptr_t) noexcept;
template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & a) noexcept;
返回 a.get() == 0
template<class T> bool operator!=(shared_ptr<T> const & a, std::nullptr_t) noexcept;
template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & a) noexcept;
返回 a.get() != 0
template<class T, class D> bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
未明确的排序规则
在C++标准中,operator< 是一种严格的弱排序
两个shared_ptr对象都为空,或者满足!(a < b) && !(b < a),那么两个智能指针相等
shared_ptr对象可以作为关联容器的key,其余的比较操作符都是被忽略的。
- swap
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
a.swap(b)
- get_pointer
template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) noexcept;
p.get()
boost::shared_ptr文档翻译的更多相关文章
- [5] 智能指针boost::shared_ptr
[1]boost::shared_ptr简介 boost::shared_ptr属于boost库,定义在namespace boost中,包含头文件#include<boost/shared_p ...
- 记录以下boost::shared_ptr的一个使用细节
shared_ptr<T>::operator->返回的是T*类型指针,非const T*指针.因此通过const shared_ptr<T>&类型的ptr可以直 ...
- 关于智能指针boost::shared_ptr
boost库中的智能指针shared_ptr, 功能强大, 且开销小,故受到广大coder的欢迎. 但在实际的使用过程中,笔者也发现了一些不足. 1.定制的删除器 shared_ptr除了可以使用默认 ...
- #include <boost/shared_ptr.hpp>
共享指针 这个智能指针命名为boost::shared_ptr,定义在boost/shared_ptr.hpp里.智能指针boost::shared_ptr基本上类似于boost::scoped_pt ...
- 智能指针剖析(下)boost::shared_ptr&其他
1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不 ...
- C++智能指针剖析(下)boost::shared_ptr&其他
1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不 ...
- 【C++】boost::shared_ptr boost::make_shared
一.shared_ptr shared_ptr作为一个动态分配的对象,当最后一个指向其内容的指针销毁(destroyed)或重置(reset),其指向的内容会被销毁(deleted).不再需要显式调用 ...
- 智能指针tr1::shared_ptr、boost::shared_ptr使用
对于tr1::shared_ptr在安装vs同一时候会自带安装,可是版本号较低的不存在.而boost作为tr1的实现品,包括 "Algorithms Broken Compiler Work ...
- boost shared_ptr weak_ptr
文档: http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/shared_ptr.htm shared_ptr构造有个原型 template< ...
随机推荐
- 【学习笔记】HTML基础:列表、表格与媒体元素
一.列表是信息资源的一种展现形式,它可以使信息结构化和条理化,并以列表的样式显示出来,以便浏览者能够快速的获取相应的信息. 1.无需列表 <ul> <li>第一项</li ...
- 自定义ExtJS文件上传
日常工作中,一般文件上传都是跟随表单一起提交的,但是遇到form表单中有许多地方有文件上传时这种方式却不是很适用,以下是我工作中用的文件上传方式: { xtype: 'fileuploadfield' ...
- csharp: DataTable结构相同的比较
) ) * pageSize; ; i++) { DataRow newdr = newdt.NewRow(); DataRow dr = dt.Rows[i]; foreach (Dat ...
- CRM——权限
一.引入权限组件 1.引入权限组件rbac 拷贝之前写好的rbac应用到CRM_demo项目下. 在settings中注册rbac的app: INSTALLED_APPS = [ 'django.co ...
- 使用CKRule实现促销管理系统
1, 常见的促销模型 促销管理系统在很多地方都有使用,大家去超市就经常体现到,感受到,不少中小型单位都其促销活动,要搞促销活动最好是有应用软件支持,这样就比较灵活管理也方便.而依靠手工处理的话效率会比 ...
- Android 解决Glide 加载图片缓慢(第一次加载不出来图片)的Bug
- Ubuntu(Debian)apt-get
Ubuntu(Debian)的aptitude与apt-get的区别和联系 最近在使用Puppet快速部署Openstack,看到一些没见过的工具,例如aptitude,在Ubuntu上有强大的a ...
- Python单元测试框架unittest使用方法讲解
这篇文章主要介绍了Python单元测试框架unittest使用方法讲解,本文讲解了unittest概述.命令行接口.测试案例自动搜索.创建测试代码.构建测试套件方法等内容,需要的朋友可以参考下 概 ...
- Linux学习笔记之Linux第一课-基本介绍
Linux简介 Linux内核最初只是由芬兰人李纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的. Linux是一套免费使用和自由传播的类Unix操作系统,是一个基 ...
- SpringMvc-reset风格
reset风格就是不用加?或者&等等符号直接通过地址栏向后台发送数据的方法 rest风格是实现 1.需要在web.xml中配置一个filter <filter> <filte ...