Boost库的智能指针shared_ptr剖析

之前的博客对Boost库的智能指针诞生的原因它们的作用,VS 和 VC下auto_ptr的不足,还解析了vc下的auto_ptr,以及Boost库的scoped_ptr和scoped_array这两个兄弟智能指针,可以查看之前的博客,今天我们直接入手shared_ptr。
shared_ptr简介
shared.ptr 是一个最像指针的“智能指针”,是boost.smart.ptr 库中最有价值、最重
要的组成部分,也是最有用的,
Boost 库的许多组件一甚至还包括其他一些领域的智能指针都使用了shared.ptr。抱歉,我实在想不出什么更恰当的词汇来形容它在软件开发中的重要性。
shared.ptr 与scoped.ptr一样包装了new 操作符在堆上分配的动态对象,但它实现的
是引用计数型的智能指针,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0) 它时才删除被包装的动态分配的对象。shared.ptr 也可以安全地放到标准容器中,并弥补了auto_ptr转移语意的缺陷,而可以用到STL容器中去。

shared_ptr类摘要分析

/*
shared._ptr 与scoped ptr 同样是用于管理new 动态分配对象的智能指针,因此功能上
有很多相似之处: 它们都重载了*和->操作符以模仿原始指针的行为,提供隐式bool 类型转换以判断指针的有效性,get () 可以得到原始指针,并且没有提供指针算术操作。
*/
/*
shared ptr 的名字表明了它与scoped ptr 的主要不同:
它是可以被安全共享的,是一个“全功能”的类,,有着正常的拷贝、赋值语义,也可以进行shared ptr间的比较,是“最智能”的智能指针。
shared.ptr 要比同为智能指针的scoped ptr 复杂许多,它的类摘要如下:
*/
template<class T> class shared_ptr
{
public:
    typedef T element_ _type;
    shared.ptr ();
    template<class Y> explicit shared_ptr (Y * p);
    template<class Y,class D> shared_ptr(Y * P,D d);
    ~shared_ptr ();

    shared_ ptr (shared_ _ptr const & r) ;
    template<class Y> explicit shared._ptr(std: :auto._ptr<Y> & r) ;
    shared.ptr & operator=(shared._ptr const & r) ;
    template<class Y> shared_ptr & operator= (shared_ptr<Y> const & r) ;
    template<class Y> shared_ ptr & operator= (std: :auto_ _ptr<Y> & r) ;
    void reset () ;
    template<class Y> void reset (Y * p) ;
    template<class Y,class D> void reset (Y * P,D d) ;
    T & operator* () const;
    operator-> () const;
    get() const;
    bool unique () const;
    long use_count () const;
    operator unspecified-bool-type () const;
    void swap(shared_ptr & b) ;
}

由类摘要我们就可以看出 shared ptr 有多种形式的构造函数,应用于各种可能的情形:
无参的shared_ptr () 创建一个持有空指针的shared_ptr;
shared ptr(Y* p)获得指向类型T 的指针p 的管理权,同时引用计数置为1。这个构造函数要求y类型必须能够转换为T类型;
shared ptr(shared.ptr const & r) 从另外一个shared_ ptr 获得指针的管理权,同时引用计数加1,结果是两个shared_ ptr 共享一个指针的管理权;
shared ptr(std: :auto_ ptr & r) 从一个auto_ ptr 获得指针的管理权,引用
计数置为1,同时auto.ptr 自动失去管理权;
operator=赋值操作符可以从另外一个shared_ptr 或auto_ ptr 获得指针的管理权,
其行为同构造函数;
shared_ ptr(Y * p,D d) 行为类似shared ptr(Y * p),但使用参数d指定了析
构时的定制删除器,而不是简单的delete.(可以自定义删除方式,不只是简单的析构释放空间,可能还要关闭其他文件描述符,打印信息等)

shared_ptr 的reset () 函数的行为与scoped_ptr 也不尽相同,它的作用是将引用计数
减1,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。带参数的reset() 则类似相同形式的构造函数,原指针引用计数减1的同时改为管理另一个指针。
shared ptr 有两个专门的函数来检查引用计数。unique() 在shared ptr 是指针的唯一
所有者时返回true(这时shared_ptr 的行为类似auto_ptr 或scoped_ptr),use_ count ()
返回当前指针的引用计数。要小心,use_ count ()应该仅仅用于测试或者调试,它不提供高效率的操作,而且有的时候可能是不可用的(极少数情形)。而unique () 则是可靠的,任何时候都可用,而且比use._count ()==1速度更快。
shared_ptr 还支持比较运算,可以测试两个shared_ptr 的相等或不相等,比较基于内
部保存的指针,相当于a.get ()==b.get ()。shared_ ptr 还可以使用operator<比较大小,是基于内部保存的指针,但不提供除<之外的比较操作,正由于可以比较,使得shared_ptr可用于容器(set map)
用法实例需要说明的是Boost库中的shared_ptr和weak_ptr已经被收入C++TR1标准,新的版本可直接在标准库中引入shared_ptr 和 weak_ptr。如下:

        std::shared_ptr<int> sp0(new int(2));
        std::shared_ptr<int> sp1(new int(11));
        std::shared_ptr<int> sp2 = sp1;
        printf("%d\n", *sp0);               // 2
        printf("%d\n", *sp1);               // 11
        printf("%d\n", *sp2);               // 11
        sp1.swap(sp0);
        printf("%d\n", *sp0);               // 11
        printf("%d\n", *sp1);               // 2
        printf("%d\n", *sp2);               // 11
        std::shared_ptr<int> sp3(new int(22));
        std::shared_ptr<int> sp4 = sp3;
        printf("%d\n", *sp3);               // 22
        printf("%d\n", *sp4);               // 22
        sp3.reset();                        
        printf("%d\n", sp3.use_count());    // 0
        printf("%d\n", sp4.use_count());    // 1
        printf("%d\n", sp3);                // 0
        printf("%d\n", sp4);                // 指向所拥有对象的地址

        std::shared_ptr<int> sp5(new int(22));
        std::shared_ptr<int> sp6 = sp5;
        std::shared_ptr<int> sp7 = sp5;
        printf("%d\n", *sp5);               // 22
        printf("%d\n", *sp6);               // 22
        printf("%d\n", *sp7);               // 22
        printf("%d\n", sp5.use_count());    // 3
        printf("%d\n", sp6.use_count());    // 3
        printf("%d\n", sp7.use_count());    // 3
        sp5.reset(new int(33));                        
        printf("%d\n", sp5.use_count());    // 1
        printf("%d\n", sp6.use_count());    // 2
        printf("%d\n", sp7.use_count());    // 2
        printf("%d\n", *sp5);               // 33
        printf("%d\n", *sp6);               // 22
        printf("%d\n", *sp7);               //22           


这是对shared_ptr作出了简单直接的剖析,shared_ptr远没有这么简单,本人建议去Boost库一探究竟,这也是C/C++程序人员一贯作风,啃啃源代码。
shared_ptr实际实现,包含了四个类型,实现结构可以给出我分析的结构图参考:
这里写图片描述
所创建的智能指针类对象ps 含有指向动态申请空间的原始指针,和一个sp_counted_impl_xx类的一个指针,这个类是引用计数的实现类;
sp_counted_impl_xx是use_count的子类,这是为了形成多态;
快去结合源码探索吧!会有很大收获!

猜你喜欢

转载自blog.csdn.net/return_cc/article/details/79420484