一个智能指针的实现

类别:VC语言 点击:0 评论:0 推荐:
一个智能指针的实现

 

       用C++写程序的人都知道内存泄漏这个问题(除非他从来不动态分内存),对STL有了解的人都知道有auto_ptr这么个智能指针,可因为它只能有一个拥有权,所以不能支持标准容器,一直不太喜欢这点。能开发出一个共享访问的智能指针就好多了(这有点像Windows内核对象)。所以,需要有个对象来管理计数问题,这个对象只能和要管理的指针共存亡,当有新的对象指向这块内存时只要把指针给它,计数加1,当一个对象析构时,只要把计数减1,是否释放是这个管理类的事儿。当计数为0时就可以自己了断了。下面我就阐述下我是怎么设计这个类的。

 

 

Template class shared_data

       shared_data是管理指针并计数的类,我们看看它都需要写哪些函数

       template<class T>

       class shared_data

       {

       private:

              friend class shared_ptr<T>;

              explicit shared_data(T* pT):_M_ptr(pT);

              ~shared_data() ;

              void operator++ ();

              operator-- ();

              T&  operator* () const ;

              T*   operator-> () const;

              bool operator== (T* pT) const ;         

              T*   get() ;

              int use_count() ;

       private:

              T*   _M_ptr;

              unsigned int    _M_nCount;

       };

       shared_ptr是我们真正要用的,所以,shared_data里的一切我们做成private就可以了,只要让shared_ptr成为自己的友员。

l        操作很简单,我们先看数据区:

1.        T* _M_ptr;

              这是我们分配出来的对象T的指针,也是我们管理的对象。

2.        unsigned int _M_nCount;

              这是我们的计数变量,初始时是1,当为0时就把自己给delete。

 

l        我们再看操作

 

1.        构造函数用来把管理的指针存入_M_ptr,析构用来释放_M_ptr。

2.        operator++()和operator—()用来增加和减少计数,在operator—()中做计数是否为0,决定在什么时候释放资源。

3.        operator==()用来判断操作符右边的T指针是否与管理的T指针是同一地址。

4.        operator*和operator->就不用说了吧。

5.        get()用来返回T*。

6.        use_count()用来获取当前有多少个引用。

 

Template class shared_ptr

       shared_ptr是用来定义和操作shared_data的类,所有同类型的shared_ptr可以有多可实例,但只有一个所共享的管理类shared_data,当两个shared_ptr类或shared_ptr和对像T的指针T*操作时,只需要对shared_data进行++和—即可。

template<class T>

       class shared_ptr

       {

              typedef shared_data<T> element;

       public:

              explicit shared_ptr(T* pT):_M_pD(NULL);

              explicit shared_ptr():_M_pD(NULL){};

              ~shared_ptr() ;

 

              // copy constructor

              shared_ptr(const shared_ptr<T>& rT) ;

              // assignment operator

              shared_ptr<T>& operator = (shared_ptr<T>& rT) ;

              shared_ptr<T>& operator = (T* pT);

              T&  operator* () const ;

              T*   operator-> () const;

              bool operator== (shared_ptr<T>& rT) const;

              bool operator== (T* pT) const;

              void reset();

       private:

              element* get_element()const  ;

              element* _M_pD;

       };

l         我们先看数据区

只有一个成员_M_pD,是shared_data对象的指针,有一shared_ptr只能拥有一个shared_data对象,shared_ptr只负责shared_data的分配,不负责释放,其它操作就是对shared_data计数的++和—操作。

 

l         公用成员函数

1.         有两个构造,一个有参数T*,用来直接分配管理类的。一个没有参数,这时的_M_pD为NULL。析构只做shared_data的—操作。

2.         拷贝构造函数用来从另一个shared_ptr中获取_M_pD并做计数++操作

3.         两个赋值函数一个是对应shared_ptr对象的,而另一个则是对应T*的,不用细说了吧。

4.         operator*() 和operator->()只是用来调用shared_data的同名函数,因为shared_data所有操作对用户是不可见的。

5.         operator==() 比shared_data多了一个,这个是用来比较_M_pD的地址是否相同,那个只是调用shared_data的同名函数(同上)。

6.         reset() 用来置空当前_M_pD,当然也要对它做—操作了。

7.         再说最后一个get_element(),一个内部函数,用来返回_M_pD,在赋值时用到。

 

 

User Operator

       为了说明我们怎么操作这个类,我们先定义一个测试类

class CTest

{

public:

       CTest(int nId){

              cout<<"CTest()"<<endl;

              m_nId = nId;

       }

 

       ~CTest(){

              cout<<"~CTest()"<<endl;

       }

 

       void ShowId()

       {

              cout<<m_nId<<endl;

       }

private:

       int m_nId;

};

 

下面看下我的测试怎么写的

 

void main()

{

    // Test constructor

    shared_ptr<CTest> t1(new CTest(1));

   

    // Test copy constructor

    shared_ptr<CTest> t2(t1);

   

    // Test assignment operator

    shared_ptr<CTest> t3;

    t3 = t2;

   

    // Test operator->

    t3->ShowId();

   

    // Test operator*

    (*t3).ShowId();

   

    // Test operator==

    shared_ptr<CTest> t4(new CTest(1));

    shared_ptr<CTest> t5(new CTest(2));

    t4 = t5;

    if (t4 == t5)

           cout<<"t4 == t5"<<endl;

    else

           cout<<"t4 != t5"<<endl;

   

    // Test operator==

    CTest *p = new CTest(123);

    shared_ptr<CTest> t6(p);

    if (t6 == p)

           cout<<"t6 == p"<<endl;

    else

           cout<<"t6 != p"<<endl;

   

    // Test operator==

    shared_ptr<CTest> p7;

    if (p7 == NULL)

           cout<<"p7 == NULL"<<endl;

   

   

    // Test reset

    shared_ptr<CTest> t8(new CTest(2));

    t8.reset(new CTest(123));

    t8->ShowId();

 

    // Test release

    shared_ptr<CTest> t9(new CTest(9));

    t9.release();

    cout<<t9.get()<<endl;

   

    // Test array

    shared_ptr<CTest> t10(new CTest(123));

    shared_ptr<CTest> t11[100];

    for (int i=0;i<100;i++) {

           t11[i] = t10;

    }

}

 

由于水平有限,可能有的地方存在问题,欢迎大家加于改善,在此给出全部代码,供大家参考

本文地址:http://com.8s8s.com/it/it806.htm