自己动手实现智能指针auto_ptr

面试的时候,我们经常会被问到如何自己动手实现智能指针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 }

测试的结果:

自己动手实现智能指针auto_ptr

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

 

你可能感兴趣的:(auto)