Kernel Space

March 11, 2007

STL 源码研读笔记(1)

Filed under: 编程珠玑 — agassi @ 1:31 am

    很久没上来写东西了,最近认真学习了一下C++,发现真是博大精深,以前可以说是白痴一个。当读到Template的时候,确实很好奇,因为自己确实想彻底弄清楚模板这块。看完后就想找个地方试试看自己看懂了没有,很自然的就想到了STL。
    STL确实是一个很实用的东西,最重要的是他写得通用而且已经作为了C++的标准放入了所有的C++ distribution中。想看看自己模板学好了没有,就去读STL。以前也想过研究这个library,后来发现自己被一大堆的”<“和”>”彻底打懵了。现在再钻进去看,觉得清楚多了。候先生的《STL源码剖析》确实是好书,可惜电子版只有前面四章,托国内同学买也未果,所以就有了这个“STL 研读笔记系列” -- 自己把感兴趣的部分读懂,然后做做笔记。

    一开始当然要从最简单的template class开始。什么最简单?vector? list? 我觉得是auto_ptr。 这个auto_ptr是一个非常简单的smart pointer类。说它简单是因为它只具有自动释放内存(析构)的功能,没有对象指针引用计数的功能。好,废话少说,这就来看看这个类。

    //一个wrapper class,这个类模拟了auto_ptr的reference类型。可以被一个传回auto_ptr值的函数赋值。
   template<typename _Tp1> struct auto_ptr_ref
     {
       _Tp1* _M_ptr;
explicit
       auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
     }; 
   //下面这个是真正的auto_ptr模板类。它唯一的成员数据就是一个模板类型的指针,这个是真正指向需要“保护”的对象的指针
   template<typename _Tp> class auto_ptr
      {
      private:
        _Tp* _M_ptr;
      public:
        typedef _Tp element_type;
       
        //构造函数,explicit表示这是一个禁止constructor conversion的构造函数,传入的参数必须是_Tp*类型
        explicit auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
        
        //同类型拷贝构造函数,参数是另外一个auto_ptr,但是这个auto_ptr要释放自己所包含的指针。正式这个move而不是copy的语义导致了“千万不要使用类型为auto_ptr的容器”!
        //这个模板类比较特殊,数据是指针,所以允许不同类型之间的拷贝
        auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
        
        //不同类型的拷贝构造函数,同样也是move的办法
        template<typename _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) {}
        //同类型的auto_ptr赋值操作符,__a释放自己包含的指针,本模板类用reset更新自己的指针为__a的指针
        auto_ptr& operator=(auto_ptr& __a) throw()
        {
        reset(__a.release());
        return *this;
        }

        //不同类型的auto_ptr赋值操作符
        template<typename _Tp1> auto_ptr& operator=(auto_ptr<_Tp1>& __a) throw()
        {
        reset(__a.release());
        return *this;
        }

        //析构函数,当auto_ptr走出scope的时候,自己释放对象。但是这里的局限就是delete,而不支持释放数组对象数组的delete []。所以决定了auto_ptr只能hold单一指针。
        ~auto_ptr() {delete _M_ptr;}

        //重载dereference操作符。
        element_type& operator* const throw()
        {
         _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
         return *_M_ptr;
        }

        //重载“member access from a pointer” 操作符。注意这里的返回值和上面的dereference返回值不同,这里返回的是成员指针。当需要调用auto_ptr->func()的时候,实际上是调用了 auto_ptr->()->func(),这个是C++内部处理的。
        element_type* operator->() const throw()
        {
           _GLIBCXX_DEBUG_ASSERT(_M_ptr !=0 );
           return _M_ptr;
        }

        //获取成员指针函数
        element_type* get() const throw() {return _M_ptr; }

        //获取成员指针函数,同时将成员指针清零
        element_type* release() throw()
        {
           element_type* __tmp = _M_ptr;
           _M_ptr = 0;
           return __tmp;
        }

        //释放成员指针所指向的对象,同时给成员指针赋新值
        void reset(element_type* __p = 0) throw()
        {
         if (__p != _M_ptr)
           {
            delete _M_ptr;
           _M_ptr = __p;
         }
         }
          
        //从auto_ptr_ref构造auto_ptr的构造函数
        auto_ptr(auto_ptr_ref<element_type> __ref) throw() : _M_ptr(__ref._M_ptr) { }

        //从auto_ptr_ref的赋值操作符,包含self-assignment 检查。前面的赋值操作符没有这个检查,因为当时只是指针的赋值,不涉及内存的释放。
        auto_ptr& operator=(auto_ptr_ref<element_type> __ref) throw()
        {
          if (__ref._M_ptr != this->get())
         {
           delete _M_ptr;
           _M_ptr = __ref._M_ptr;
         }
          return *this;
        }

        //本auto_ptr到其他任意类型auto_ptr_ref的conversion操作符重载
        template<typename _Tp1>
          operator auto_ptr_ref<_Tp1>() throw()
          { return auto_ptr_ref<_Tp1>(this->release()); }

        //本auto_ptr到其他任意类型的auto_ptr的conversion操作符重载
        template<typename _Tp1>
          operator auto_ptr<_Tp1>() throw()
          { return auto_ptr<_Tp1>(this->release()); }
    };

    好了,写到这里自己也温习了一遍,也收获不小,下次再选一个稍微复杂一点的来分析一下。
   

Advertisements

1 Comment »

  1. Thanks, always good posts on your blog!

    Comment by Desktopjunk — April 22, 2007 @ 11:00 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: