scoped_ptr

先看一个简单的例子:

#include <iostream>
using namespace std;

#include <boost/scoped_ptr.hpp>
using namespace boost;

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
    
    ~A() {
        cout << "A::~A()" << endl;
    }
};

/*
 * 
 */
int main(int argc, char** argv) {

    scoped_ptr<A> a(new A);
    return 0;
}
程序运行后输出结果:

A::A()
A::~A()
很好,对象被销毁了。


scoped_ptr被设计用来取代std::auto_ptr.

回忆一下auto_ptr的功能,参考我以前的老文章:http://blog.csdn.net/sheismylife/article/details/1694939

auto_ptr也能够像上面例子里自动回收new出来的对象,差别在于auto_ptr有一个所有权转移的特性。这在实现异常安全的代码中是非常有用的。参考herb sutter的exceptional c++系列书籍。

不过在boost::shared_ptr也由于采用了引用计数的实现,比auto_ptr的所有权转移特性更强,而且能够被stl容器接受,不像auto_ptr不能用于stl容器。 

所以auto_ptr从宠儿变成了弃儿,最新的C++11标准已经把它废除。


scoped_ptr非常简单,不支持所有权转移。这种实现代码就是利用了前面我的noncopyable文章里面介绍的基本原理。但是实际上并没有从noncopyable继承,不要被文档上的例子代码忽悠。http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/scoped_ptr.htm

真正的实现代码:

template<class T> class scoped_ptr // noncopyable
{
private:

    T * px;

    scoped_ptr(scoped_ptr const &);
    scoped_ptr & operator=(scoped_ptr const &);

    typedef scoped_ptr<T> this_type;

    void operator==( scoped_ptr const& ) const;
    void operator!=( scoped_ptr const& ) const;
私有的copy constructor和copy assignment ,禁止了scoped_ptr之间的拷贝。所有权不能转移了。

同时比较操作符也被禁止了,外面无法调用。

boost里面的实现代码很喜欢用this_type来简化内部的类型引用,值得推荐。

public:

    typedef T element_type;

    explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
    {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost::sp_scalar_constructor_hook( px );
#endif
    }

#ifndef BOOST_NO_AUTO_PTR

    explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() ) // never throws
    {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost::sp_scalar_constructor_hook( px );
#endif
    }

#endif

    ~scoped_ptr() // never throws
    {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost::sp_scalar_destructor_hook( px );
#endif
        boost::checked_delete( px );
    }

第一个构造函数接受普通指针,保存起来。

第二个构造函数接受auto_ptr,并且通过调用auto_ptr的release函数让auto_ptr不再管理指针的生命周期,然后自己保存该指针。

析构函数利用boost::checked_delete释放px指向的对象。参考我的另一文章:http://blog.csdn.net/sheismylife/article/details/8277908

    T & operator*() const // never throws
    {
        BOOST_ASSERT( px != 0 );
        return *px;
    }

    T * operator->() const // never throws
    {
        BOOST_ASSERT( px != 0 );
        return px;
    }

    T * get() const // never throws
    {
        return px;
    }
operator* 和 operator-> 使得scoped_ptr就像普通指针一样工组。
get可以获取里面保存的裸指针。

// get_pointer(p) is a generic way to say p.get()

template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
{
    return p.get();
}
全局模板函数可以获得p包含的裸指针。

    void swap(scoped_ptr & b) // never throws
    {
        T * tmp = b.px;
        b.px = px;
        px = tmp;
    }

template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
{
    a.swap(b);
}

    void reset(T * p = 0) // never throws
    {
        BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
        this_type(p).swap(*this);
    }
成员函数swap可以交换b和this的裸指针。

全局模板函数swap可以交换两个参数内部的裸指针。

reset也利用了这个swap成员函数 将this内部的裸指针交换给了临时对象this_type(p), 

因此,如果:

1.调用reset不传递参数,就是清空了自己的裸指针。

或者

2.调用reset传递了另一个指针,就是用这个指针替换了this拥有的裸指针。

不管是哪一种情况,this拥有的原来的裸指针都会被调用delete销毁。因为临时对象this_type(p)通过交换拿到这个指针后,都会在退出swap函数时销毁它。

scoped_ptr也支持if(p) 或者 if(!p)的用法,这里我们再次看到将实现代码放在一个文件中,然后include进来的做法:

// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
operator_boo.hpp文件内容如下:

#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)

    operator bool () const
    {
        return px != 0;
    }

#elif defined( _MANAGED )

    static void unspecified_bool( this_type*** )
    {
    }

    typedef void (*unspecified_bool_type)( this_type*** );

    operator unspecified_bool_type() const // never throws
    {
        return px == 0? 0: unspecified_bool;
    }

#elif \
    ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
    ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
    ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )

    typedef T * (this_type::*unspecified_bool_type)() const;

    operator unspecified_bool_type() const // never throws
    {
        return px == 0? 0: &this_type::get;
    }

#else

    typedef T * this_type::*unspecified_bool_type;

    operator unspecified_bool_type() const // never throws
    {
        return px == 0? 0: &this_type::px;
    }

#endif

    // operator! is redundant, but some compilers need it
    bool operator! () const // never throws
    {
        return px == 0;
    }
其他的编译器不管,GCC版本的实现代码是:

    typedef T * this_type::*unspecified_bool_type;

    operator unspecified_bool_type() const // never throws
    {
        return px == 0? 0: &this_type::px;
    }
这里unspecified_bool_type是一个类的成员指针类型,指向了scopec_ptr<T>内部的T的指针。有点拗口:

1.typedef表明这是个类型定义,所以unspecified_bool_type是个类型

2.this_type::*表明这个unspecified_bool_type是个成员指针类型

3.T* 表明这个unspecified_bool_type指针类型指向的是T*类型

整个operator实现就是一个类型转换操作符,如果px为0,则返回0,否则返回内部保存的px裸指针的地址,按照C++规定,只要px裸指针不为空,对它取地址结果是true. 因此下面的代码获得true的返回值:

    scoped_ptr<A> a(new A);
    if (a) {
        cout << "ok" << endl;
    }











你可能感兴趣的:(scoped_ptr)