自己动手实现智能指针auto_ptr

时间:2020-12-17 11:45:17

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

具体代码如下:

 template<class T>
class Auto_ptr {
private:
T *ptr; //真正的指针值
mutable bool owns; //是否拥有该指针
public:
//不可以隐式转化的构造函数
explicit Auto_ptr(T *p = ):ptr(p),owns((bool)p){} //不能隐式转化,例如Auto_ptr<int> Ap = new int(1024) //error
//复制构造函数
//Auto_ptr(const Auto_ptr& a):ptr(a.ptr),owns(a.owns){ a.owns = 0;}
//泛化版的复制构造函数
template <class U>
Auto_ptr(const Auto_ptr<U>& a):ptr(a.ptr),owns(a.owns){ a.owns = ;} //重载赋值操作符
Auto_ptr& operator=(const Auto_ptr& a)
{
if(&a != this) //防止自身赋值
{
if(owns)
delete ptr;
owns = a.owns;
ptr = a.ptr;
a.owns = ;
}
}
//泛化版的重载赋值操作符
template<class U>
Auto_ptr& operator=(Auto_ptr<U>& a)
{
if (&a != this)
{
if(owns)
delete ptr;
owns = a.owns;
ptr = a.ptr;
a.owns = false;
}
return *this;
}
T& operator *() const {return *ptr;}
T* operator ->() const {return ptr;}
T* get() const { return ptr;}
void reset(T *p = )
{
if(owns)
{
if(ptr != p) //如果p 和 ptr的值不同
{
delete ptr; //删除原来指向的对象
} //else付过相同肯定不能删除啊
}
ptr = p; //这里赋值时安全的,机试ptr和p原来相等
}
T* release() const{ owns = false;return ptr;}
~Auto_ptr(){if(owns) {cout << "析构!"<< endl;delete ptr;}}
};

测试代码如下:

 #include<iostream>

 using namespace std;

 int main()
{
Auto_ptr<int> Ap;
Auto_ptr<int> Ap1(new int());
//Auto_ptr<int> Ap2 = new int(1024); //error
//if(Ap == NULL) //error
if(Ap.get() == NULL)
{
cout << "Ap is NULL!" << endl;
}
cout << "Before = Ap1 value is:" << Ap1.get() << endl;
Auto_ptr<int> Ap3 ;
Ap3 = Ap1;
cout << "After = Ap1 value is:" << Ap1.get() << endl;
int *p = Ap3.release();
cout << "Ap3 value is:" << Ap3.get() << endl;
Ap3.reset(new int());
cout << "Ap3 value is:" << Ap3.get() << endl;
return ;
}

测试的结果:

自己动手实现智能指针auto_ptr

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