auto_ptr实现原理是资源管理权的转移,即是说构造函数创建对象时获得资源管理权,析构对象时撤销管理权,这样的管理权的转移,带来的最重要的缺点就是安全性问题,下面具体阐述一下新旧版本的auto_ptr方便理解。
模拟实现旧版本的auto_ptr:
旧版本的auto_ptr是多定义了一个成员对象_symbol来标识该成员对象的资源管理权,在调用构造函数创建对象时获得资源管理权,即_symbol置为true,在调用拷贝构造函数、赋值运算符重载、析构函数时将其值为false.
#include<iostream>
using namespace std;
template<class T>
class Autoptr
{
public:
Autoptr<T>(T*ptr = NULL)
:_ptr(ptr)
, _symbol(true)
{}
Autoptr<T>(const Autoptr<T>&a)
:_ptr(a._ptr)
, _symbol(true)
{
a._symbol = false;
}
Autoptr<T>&operator=(const Autoptr<T>&a)
{
if (this != &a)
{
delete this->_ptr;
_ptr = a._ptr;
_symbol = ture;
a._symbol = false;
}
return *this;
}
T&operator*()//解引用操作符重载
{
return *(this->_ptr);
}
T&operator*()const//const型解引用操作符重载
{
return *(this->_ptr);
}
T*operator->()//取地址操作符重载
{
return this->_ptr;
}
T*operator->()const//const型取地址操作符重载
{
return this->_ptr;
}
~Autoptr<T>()
{
if (_ptr)
{
delete _ptr;
_symbol = false;
}
}
private:
T* _ptr;
mutable bool _symbol;//在const修饰的成员函数中要对类的某个数据成员进行修改,该数据成员定义声明必须加mutale关键字。
};
int main()
{
Autoptr<int>p1(new int);//
int i = 1;
if (i == 1)
{
Autoptr<int>p2(p1);
}
*p1 = 10;
system("pause");
return 0;
}
原因是:p2出了if作用域会释放,将自己的空间释放,当再次为p1赋值将导致寻址失败,而导致程序崩溃。
新版的auto_ptr的实现:
继承旧版的auto_ptr实现的思想,将symbol去掉,在使用拷贝构造、赋值运算符重载后直接将原对象置空。
//新版
template<class T>
class Auto_ptr
{
public:
Auto_ptr(T*ptr=NULL)
: _ptr(ptr)
{}
Auto_ptr( /*const*/ Auto_ptr<T>&a)
:_ptr(a._ptr)
{
a._ptr = NULL;
}
Auto_ptr<T>&operator=(const Auto_ptr<T>&a)
{
if (this != &a)
{
delete _ptr;
_ptr = a._ptr;
a._ptr = NULL;
}
return *this;
}
T&operator*()//解引用操作
{
return *(this->_ptr);
}
T&operator*()const//解引用操作
{
return *(this->_ptr);
}
T*operator->()//取地址操作
{
return this->_ptr;
}
T*operator->()const//const取地址操作
{
return this->_ptr;
}
~Auto_ptr<T>()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
private:
T* _ptr;
};
int main()
{
Auto_ptr<int> p(new int(1));
Auto_ptr<int> p1(p);
Auto_ptr<int> p2 = p1;
*p= 10;//这样就会报错误。
system("pause");
return 0;
}