[boost] shared_ptr 概述

4 篇文章 0 订阅

翻译来自 : http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/shared_ptr.htm

3. 概要

namespace boost {

  class bad_weak_ptr: public std::exception;

  template<class T> class weak_ptr;

  template<class T> class shared_ptr {

    public:

      typedef T element_type;

      shared_ptr(); // never throws
      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);
      ~shared_ptr(); // never throws

      shared_ptr(shared_ptr const & r); // never throws
      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
      template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws
      template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
      template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);

      shared_ptr & operator=(shared_ptr const & r); // never throws
      template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

      void reset(); // never throws
      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, T * p); // never throws

      T & operator*() const; // never throws
      T * operator->() const; // never throws
      T * get() const; // never throws

      bool unique() const; // never throws
      long use_count() const; // never throws

      operator unspecified-bool-type() const; // never throws

      void swap(shared_ptr & b); // never throws
  };

  template<class T, class U>
    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

  template<class T, class U>
    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

  template<class T, class U>
    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws

  template<class T> T * get_pointer(shared_ptr<T> const & p); // never throws

  template<class T, class U>
    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws

  template<class T, class U>
    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws

  template<class T, class U>
    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws

  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);
}


4. 成员

element_type

typedef T element_type;    //模板参数类型的声明

constructors

shared_ptr(); // never throws

作用: 构造一个空的shared_ptr

后置条件: use_count() == 0 && get() == 0.    // postconditions 后置条件,是指在一段代码或者操作执行完以后,给出的条件必须为真.也就是说当执行完shared_ptr() 之后,断言 use_count() == 0 && get() == 0 为真.

异常: 不抛出异常

[不抛出异常的保证是很重要的,因为 reset() 的异常保证与默认构造函数有关系 这个保证表明默认构造函数必须不能申请内存]

template<class Y> explicit shared_ptr(Y * p);

需求: p必须可以转换为T*[注1],Y必须是一个完整类型[注2]. 表达式 delete p 必须是良好行为的,必须不能调用未定义行为,必须不能抛出异常(这个其实主要是对类型p析构函数的要求).

作用: 创建一个拥有指针 p 的shared_ptr.

后置条件: use_count() == 1 && get() == p.

异常: std::bad_alloc, 或者由实现决定的,当在获取内存以外的资源失败时抛出的异常.

异常安全性: 如果有异常抛出,那么delete p 会被调用.

注意: p 必须指向一个通过c++ new表达式申请的对象,或者为空指针. 当p 是空指针时, 前置条件中的 use_count() == 1 依然成立,因为删除一个空指针是无害的.

[这个构造函数之所以会是模板函数,是为了记录 p 的实际类型.即使类型T并没有虚析构函数或者T就是空类型,shared_ptr的析构函数也会删除与p的实际类型完全相同的指针.]

[实现时放弃了对于侵入式计数的支持,因为侵入式计数暴露了太多实现细节,而且与weak_ptr的交互也不是很好.当前实现使用了 enable_shared_from_this, , 来解决 "shared_ptr fromthis"问题.]

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);

需求: p必须可以转换为T*.D必须是可拷贝的.D的拷贝构造以及析构函数不能抛出异常. 表达式d(p)必须为行为良好的,不许不能调用未定义行为,必须不能抛出异常. A 必须是一个Allocator,在C++标准的20.1.5(Allocator需求)中有对内存分配器的描述.

作用:构造一个拥有指针p,以及删除器d的shared_ptr.第二个构造函数使用a的拷贝分配内存.

前置条件: use_count() == 1 && get() == p.

异常:std::bad_alloc, 或者由实现决定的,当在获取内存以外的资源失败时抛出的异常. 

异常安全:如果抛出异常,d(p)将会被调用.Exception safety: If an exception is thrown, d(p) is called.

注意: 当删除p所指向的对象时,d(p)将会被调用,其中d为保存在shared_ptr中的删除器拷贝.

[可以通过返回shared_ptr的工厂方法(make_shared()以及allocate_shared())定制的删除器,使用户被隔离在定制的内存分配策略之外.因为删除器并不是类型的一部分,修改内存分配策略不会破坏源代码以及二级制的兼容性,所以客户不需要重新编译.

定制删除器不会带来额外的性能负担.其他的share_ptr特性也需要特别的删除器支持.

D的拷贝构造不能抛出异常,这是因为删除器是传值操作.如果D的拷贝构造函数抛出异常,指针就不会被删除.去掉这个需求的方法是传引用.

但是当引用与右值在一起时,又会引起一些问题.一个常引用需要使用const操作符,可能会引发一次拷贝.非常引用不能绑定到一个右值.]

shared_ptr(shared_ptr const & r); // never throws
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);  //never throws

    作用: 如果r为空,构造一个空shared_ptr.否则,构造一个与r共享所有权的shared_ptr.

    前置条件: get() == r.get() && use_count() == r.use_count().

    异常: 不抛出异常.

template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p); // never throws

    作用: 构造一个与r共享所有权的shared_ptr,并且保存p.(语义类似r的别名)

    前置条件: get() == p && use_count() == r.use_count().

    异常: 不抛出异常.

template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);

    作用: 构造一个与r共享所有权的shared_ptr,并且保存一份r中的指针的拷贝.

    前置条件: use_count() == r.use_count().

    异常: 当r.use_count()=0时,抛出bad_weak_ptr 

    异常安全性:如果抛出异常,构造函数无效.

template<class Y> shared_ptr(std::auto_ptr<Y> & r);

         作用: 构造一个shared_ptr,就像保存一份 r.release()的拷贝一样.(r.release()放弃对指针的所有权,并且返回原来持有的指针)

         前置条件:use_count()==1;

         异常:std::bad_alloc(),或者由实现决定的,当在获取内存以外的资源失败时抛出的异常.
            异常安全性:如果抛出异常,那么构造函数无效.

[???]

destructor

~shared_ptr(); // never throws

             作用:    

                        如果*this为空,又或者与另外一个shared_ptr实例共享一个对象(use_count()>1),那么将没有副作用;

                  否则,如果拥有一个指针p,一个删除器d,那么d(p)将会被调用;

                  否则,*this拥有一个指针p,delete p会被调用.

         异常: 不抛出异常

assignment

shared_ptr & operator=(shared_ptr const & r); // never throws
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);

             作用: 与shared_pr(r).swap(*this)相同.

             返回值: *this.

             注意: 临时对象的构造和析构会更新use_count(),但是这不被认为是可以察觉的副作用[注3].实现可以自由选择来实现这个函数,比如不创建临时对象.需要注意的是,在下面的例子中:

       

shared_ptr<int> p(new int);
shared_ptr<void> q(p);
p = p;
q = p;
上面  p=p   以及  q=p  这两个赋值都需要是 NO-OPs [注4];

reset

void reset(); // never throws
              作用: 与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, T * p); // never throws
                作用: 与shared_ptr(r,p).swap(*this)相同;

indirection

T & operator*() const; // never throws
需求: 保存的指针p必须不能等于0

返回值: 保存指针指向对象的引用

异常:不抛出异常

T * operator->() const; // never throws
需求: 保存的指针p必须不能等于0

返回值: 指针

异常:不抛出异常

get

T * get() const; // never throws
返回值: 保存的指针

异常:不抛出异常

unique

bool unique() const; // never throws

返回值: use_count()==1

异常:不抛出异常

注意: [???]

use_count

long use_count() const; // never throws

返回: shared_ptr对象的个数.

异常:不抛出异常

注意: use_count()不必高效.仅仅是调试目的.

conversions

operator unspecified-bool-type () const; // never throws

返回:一个未指定的值,当作为bool值使用时,等于 get() != 0;

异常:不抛出异常

注意: 转换操作符使shared_ptr可以用作bool值,如  if (p && p->valid()) {}.  转换的实际类型是一个指向成员函数的指针,避免许多隐式转换的陷阱.

swap

void swap(shared_ptr & b); // never throws

作用: 交换两个shared_ptr 的内容

异常: 不抛出异常

Free Functions

comparison

template<class T, class U>
  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

返回: a.get() == b.get();

异常: 不抛出异常

template<class T, class U>
  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

返回: a.get() != b.get()

异常: 不抛出异常


template<class T, class U>
  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws


返回:  不确定的值[注: 这里并不是指数值随机,而是指比较获得的值满足以下条件的值就可以] :  

              1.  operator < 是一个 strict weak ordering (C++标准25.3有提到)  [注5]

               2. 只有当两个 shared_ptr 共享一个指针的权限,或者 两个 shared_ptr 都为空时,两个 shared_ptr 才相等.

Swap

template<class T>
  void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws

作用:  与 a.swap(b) 相同

异常: 无

注意: 匹配 std::swap 接口,做为泛型编程的辅助.


get_pointer

template<class T>
  T * get_pointer(shared_ptr<T> const & p); // never throws

返回: p.get();

异常: 无

注意: 用于泛型编程.被  mem_fn使用


static_pointer_cast

template<class T, class U>
  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws

需求: 表达式 static_cast<T*>(r.get())必须是行为良好的.

返回: 如果r为空,返回 空 shared_ptr<T>;否则,返回一个 shared_ptr<T> 类型的智能指针,保存 static_cast<T*>(r.get()) 的拷贝.与r共享所有权.

异常: 无

注意: 与表达式 shared_ptr<T>(static_cast<T*>(r.get())) 并不相同. shared_ptr<T>(static_cast<T*>(r.get()))最终会导致未定义行为,因为尝试删除同一个r.get().


const_pointer_cast

template<class T, class U>
  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
需求: 表达式const_cast<T*>(r.get())必须是行为良好的

返回: 如果r为空,则返回空shared_ptr<T>;否则,返回一个shared_ptr<T>类型的智能指针,保存const_cast<T*>(r.get())的拷贝.与r共享所有权

异常:无

注意: 与表达式 shared_ptr<T>(const_cast<T*>(r.get())) 并不相同. shared_ptr<T>(const_cast<T*>(r.get()))最终会导致未定义行为,因为尝试删除同一个r.get().

dynamic_pointer_cast

template<class T, class U>
  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
需求: 表达式dynamic_cast<T*>(r.get())必须是行为良好的;

返回:     如果dynamic_cast<T*>(r.get())返回一个为空值(有可能因为转换失败返回空值),则返回一个shared_ptr<T>类型的智能指针.与r共享所有权.否则,返回一个空的shared_ptr<T> 对象

异常:无

注意:与表达式shared_ptr<T>(dynamic_cast<T*>(r.get()))并不相同.shared_ptr<T>(dynamic_cast<T*>(r.get()))最终会导致未定义行为,因为尝试删除同一个r.get();

operator<<

template<class E, class T, class Y>
    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
效果:os<<p.get();

返回: os

get_deleter

template<class D, class T>
    D * get_deleter(shared_ptr<T> const & p);
返回:如果*this拥有一个(非CV类型)D类型的删除器d,则返回&d,否则返回空.

异常:无







注1:   这里指隐式转换,包括标准转换以及用户自定义转换;

注2:  完整类型,这里是相对不完整类型来说的.如果一个类型只声明但是没有定义,或者一个对数组类型具有未知的大小或者元素类型,那么这个类型就是一个不完整定义的对象类型.也就是说这种类型对象的大小和布局是未知的,不完整定义的对象类型和空类型被称作不完整类型.[3.9.6]

注3:  负作用是指函数调用对外界有影响.比如修改全局变量.详细请见: http://en.wikipedia.org/wiki/Side_effect_%28computer_science%29

注4:   NO-OPs是指函数的调用没有任何作用,  比如   C++     i+1;    这个表达式,只有加1,但是没有返回值.这就叫做 NO-OPs ,详细请见:http://en.wikipedia.org/wiki/NOP

注5:   order theory:http://en.wikipedia.org/wiki/Order_theory      strict weak orderinghttp://en.wikipedia.org/wiki/Strict_weak_ordering





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值