scoped_ptr源码


/* E:\Program Files\CodeGear\RAD Studio\7.0\include\boost_1_35\boost/checked_delete.hpp 24: */
namespace boost
{
    template<class T> inline void checked_delete(T * x)
    {
        typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
        (void) sizeof(type_must_be_complete);
        delete x;
    }

    template<class T> inline void checked_array_delete(T * x)
    {
        typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
        (void) sizeof(type_must_be_complete);
        delete [] x;
    }

    template<class T> struct checked_deleter
    {
        typedef void result_type;
        typedef T * argument_type;

        void operator()(T * x) const
        {
            boost::checked_delete(x);
        }
    };

    template<class T> struct checked_array_deleter
    {
        typedef void result_type;
        typedef T * argument_type;

        void operator()(T * x) const
        {
            boost::checked_array_delete(x);
        }
    };
}


/* E:\Program Files\CodeGear\RAD Studio\7.0\include\boost_1_35\boost/scoped_ptr.hpp 23: */
namespace boost
{
    template<class T> class scoped_ptr
    {
    private:
        T * ptr;

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

        typedef scoped_ptr<T> this_type;

    public:
        typedef T element_type;

        explicit scoped_ptr(T * p = 0): ptr(p)
        {
        }
   /*构造函数,存储p的一份拷贝。注意,p 必须是用operator new分配的,或者是null。在构造的时候,
   不要求T必须是一个完整的类型。当指针p是调用某个allocation函数的结果而不是直接调用new得到的时
   候很有用:因为这个类型不必是完整的,只需要类型T的一个前置声明就可以了。这个构造函数不会抛出
   异常。*/

        explicit scoped_ptr(std::auto_ptr<T> p): ptr(p.release())
        {
        }
   /*从一个auto_ptr手中接过控制权,指向auto_ptr指针所指的对象,并且auto_prt指针不再指向该对象*/

        ~scoped_ptr()
        {
            boost::checked_delete(ptr);
        }
   /*删除所指对象。类型T在被销毁时必须是一个完整的类型。如果scoped_ptr在它被析构时并没有
   占有资源,它就什么都不做。这个析构函数不会抛出异常。*/

        void reset(T * p = 0)
        {
            ((p == 0 || p != ptr) ? (void)0 : _assert( "p == 0 || p != ptr", "E:\\Program Files\\CodeGear\\RAD Studio\\7.0\\include\\boost_1_35\\boost/scoped_ptr.hpp", 82));
            this_type(p).swap(*this);
        }
   /*重置一个 scoped_ptr 就是删除它已保存的指针,如果它有的话,并重新保存 p。 通常,资源的生存期
    管理应该完全由scoped_ptr自己处理,但是在极少数时候,资源需要在scoped_ptr的析构之前释放,或
    者scoped_ptr要处理它原有资源之外的另外一个资源。这时,就可以用reset,但一定要尽量少用它。
    (过多地使用它通常表示有设计方面的问题) 这个函数不会抛出异常。*/

        T & operator*() const
        {
            ((ptr != 0) ? (void)0 : _assert( "ptr != 0", "E:\\Program Files\\CodeGear\\RAD Studio\\7.0\\include\\boost_1_35\\boost/scoped_ptr.hpp", 88));
            return *ptr;
        }
   /*返回一个到被保存指针指向的对象的引用。由于不允许空的引用,所以解引用一个拥有空指针
    的scoped_ptr将导致未定义行为。如果不能肯定所含指针是否有效,就用函数get替代解引用。
    这个函数不会抛出异常。*/

        T * operator->() const
        {
            ((ptr != 0) ? (void)0 : _assert( "ptr != 0", "E:\\Program Files\\CodeGear\\RAD Studio\\7.0\\include\\boost_1_35\\boost/scoped_ptr.hpp", 94));
            return ptr;
        }
   /*返回保存的指针。如果保存的指针为空,则调用这个函数会导致未定义行为。如果不能确定指针是否
    空的,最好使用函数get。这个函数不会抛出异常。*/

        T * get() const
        {
            return ptr;
        }
   /*返回保存的指针。应该小心地使用get,因为它可以直接操作裸指针。但是,get使得你可以测试保存的
    指针是否为空。这个函数不会抛出异常。get通常用于调用那些需要裸指针的函数。*/


        typedef T * this_type::*unspecified_bool_type;

        operator unspecified_bool_type() const
        {
            return ptr == 0? 0: &this_type::ptr;
        }
   /*返回scoped_ptr是否为非空。返回值的类型是未指明的,但这个类型可被用于Boolean的上下文中。
    在if语句中最好使用这个类型转换函数,而不要用get去测试scoped_ptr的有效性*/

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

        void swap(scoped_ptr & b)
        {
            T * tmp = b.ptr;
            b.ptr = ptr;
            ptr = tmp;
        }
   /*交换两个scoped_ptr的内容。这个函数不会抛出异常。*/
    };

    template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b)
    {
        a.swap(b);
    }
 /*个函数提供了交换两个scoped pointer的内容的更好的方法。之所以说它更好,是因为
  swap(scoped1,scoped2) 可以更广泛地用于很多指针类型,包括裸指针和第三方的智能指针。
  [2] scoped1.swap(scoped2) 则只能用于它的定义所在的智能指针,而不能用于裸指针。*/

    template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
    {
        return p.get();
    }
}

用法:

scoped_ptr的用法与普通的指针没什么区别;最大的差别在于你不必再记得在指针上调用delete,还有复制是不允许的。典型的指针操作(operator*operator->)都被重载了,并提供了和裸指针一样的语法。用scoped_ptr和用裸指针一样快,也没有大小上的增加,因此它们可以广泛使用。使用boost::scoped_ptr时,包含头文件"boost/scoped_ptr.hpp". 在声明一个scoped_ptr时,用被指物的类型来指定类模板的参数。例如,以下是一个包含std::string指针的scoped_ptr

boost::scoped_ptr<std::string> p(new std::string("Hello"));

scoped_ptr被销毁时,它对它所拥有的指针调用delete

区别:

scoped_ptrauto_ptr间的区别主要在于对拥有权的处理。auto_ptr在复制时会从源auto_ptr自动交出拥有权,而scoped_ptr则不允许被复制。
原文地址:https://www.cnblogs.com/yuanxiaoping_21cn_com/p/1555791.html