面试的时候,我们经常会被问到如何自己动手实现智能指针auto_ptr.今天我就一边参考STL库中的源代码,一边将auto_ptr的实现敲一遍。

auto_ptr归根到底是一个模版类,那么这个类要实现哪些功能呢?如下:

/*
一个智能指针应该有以下操作:
1.Auto_ptr<T> ap;            //创建名为ap的为绑定Auto_ptr对象
2.Auto_ptr<T> ap(p);         //创建 ap 的Auto_ptr对象,ap用友指针 p 指向的对象。该构造函数为explicit
3.Auto_ptr<T> ap1(ap2)              //创建名为ap1的Auto_ptr对象,ap1保存原来存在ap2中的指针。将所有权转给ap1,ap2成为未绑定的Auto_ptr对象
4.ap1 = ap2            //将所有权从ap2转给ap1。删除ap1指向的对象并且使ap1指向ap2指向的对象,使ap2成为未绑定的
5.~ap                //析构函数。删除ap指向的对象
6.*ap                                            //返回对ap所绑定对象的引用
7.ap->                                          //返回ap保存的指针
8.ap.reset(p)                                //如果ap与p的值不同,则删除ap指向的独享并且将ap绑定到p
9.ap.release()                               //返回ap所保存的指针并且是ap成为未绑定的
10.ap.get()                                   //返回ap保存的指针
*/

具体代码如下:

 1 template<class T>
 2 class Auto_ptr {
 3 private:
 4     T *ptr;        //真正的指针值
 5     mutable bool owns;    //是否拥有该指针
 6 public:
 7     //不可以隐式转化的构造函数
 8     explicit Auto_ptr(T *p = 0):ptr(p),owns((bool)p){}    //不能隐式转化,例如Auto_ptr<int> Ap = new int(1024) //error
 9     //复制构造函数
10     //Auto_ptr(const Auto_ptr& a):ptr(a.ptr),owns(a.owns){ a.owns = 0;}
11     //泛化版的复制构造函数
12     template <class U>
13     Auto_ptr(const Auto_ptr<U>& a):ptr(a.ptr),owns(a.owns){ a.owns = 0;}
14 
15     //重载赋值操作符
16     Auto_ptr& operator=(const Auto_ptr& a)
17     {
18         if(&a != this)    //防止自身赋值
19         {
20             if(owns)
21                 delete ptr;
22             owns = a.owns;
23             ptr  = a.ptr;
24             a.owns = 0;
25         }
26     }
27     //泛化版的重载赋值操作符
28     template<class U>
29     Auto_ptr& operator=(Auto_ptr<U>& a)
30     {
31         if (&a != this)
32         {
33             if(owns)
34                 delete ptr;
35             owns = a.owns;
36             ptr  = a.ptr;
37             a.owns = false;
38         }
39         return *this;
40     }
41     T& operator  *() const {return *ptr;} 
42     T* operator ->() const {return ptr;}
43     T* get() const { return ptr;}
44     void reset(T *p = 0)
45     {
46         if(owns)
47         {
48             if(ptr != p)    //如果p 和 ptr的值不同    
49             {
50                 delete ptr;    //删除原来指向的对象
51             }                //else付过相同肯定不能删除啊
52         }
53         ptr = p;            //这里赋值时安全的,机试ptr和p原来相等
54     }
55     T* release() const{ owns = false;return ptr;}
56     ~Auto_ptr(){if(owns) {cout << "析构!"<< endl;delete ptr;}}
57 };

测试代码如下:

 1 #include<iostream>
 2 
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     Auto_ptr<int> Ap;
 8     Auto_ptr<int> Ap1(new int(1024));
 9     //Auto_ptr<int> Ap2 = new int(1024);    //error
10     //if(Ap == NULL)        //error
11     if(Ap.get() == NULL)
12     { 
13         cout << "Ap is NULL!" << endl;
14     }
15     cout << "Before = Ap1 value is:" << Ap1.get() << endl;
16     Auto_ptr<int> Ap3 ;
17     Ap3 = Ap1;
18     cout << "After  = Ap1 value is:" << Ap1.get() << endl;
19     int *p = Ap3.release();
20     cout << "Ap3 value is:" << Ap3.get() << endl; 
21     Ap3.reset(new int(12));
22     cout << "Ap3 value is:" << Ap3.get() << endl;
23     return 0;
24 }

测试的结果:

由上图我们可以看到Ap1在 赋值=之前和之后都指向的地址都是00620FB8,说明赋值并没有改变智能指针的指向,只是将拥有的标志owns改变了。通过reset函数可以重新绑定智能指针!

 

posted on 2014-04-21 21:43  水目沾  阅读(565)  评论(1编辑  收藏  举报