RAII(Resource Acquisition Is Initialization):
资源分配即初始化,定义封装一个类,用来实现调用构造函数时就可完成资源的分配和初始化,在调用析构函数就可完成资源的清理,以实现对资源的初始化和清理。
资源分配即初始化,定义封装一个类,用来实现调用构造函数时就可完成资源的分配和初始化,在调用析构函数就可完成资源的清理,以实现对资源的初始化和清理。
常见的智能指针有:auto_ptr / scoped_ptr / scoped_array / shared_ptr / shared_array
本文主要是对AutoPtr指针的学习记录,后面也会有其他的智能指针的学习记录的,^_^
智能指针:能智能化管理动态开辟空间的内存释放
特点:
1、智能指针管理的是一块内存的释放
2、智能指针是一个类,有类似指针的功能
1、智能指针管理的是一块内存的释放
2、智能指针是一个类,有类似指针的功能
这里,我想用“
目的式
”的方法,记录 对AutoPtr的学习
首先,大致写出AutoPtr类的
基本构架
template <class T>
class AutoPtr
{
public:
AutoPtr(T * ptr)
:_ptr(ptr)
{ }
~AutoPtr()
{
cout << "delete" << _ptr << endl;
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
private:
T * _ptr;
};
解析:
上面的代码是存在问题的,class AutoPtr只是实现了构造函数和析构函数,对于拷贝构造函数和赋值运算符重载时系统默认的,在前面的学习模拟string 中,可以知道,系统默认的这两个函数时存在“浅拷贝”问题的,致使程序运行出错。 string的解决方法是 使用“深拷贝”,但AutoPtr不能用深拷贝来解决(智能指针必须是指针指向同一块内存空间)。
解决浅拷贝总的思想是:
管理权的转移
1、旧版的AutoPtr
主要变量是_ptr,_owner,用bool型的_owner来控制权限转移,当它为false值时释放空间,保证释放一次。
template<typename T>
class AutoPtr
{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
, _owner(true)
{}
AutoPtr(AutoPtr<T>& ap)
:_ptr(ap._ptr)
, _owner(true)
{
ap._owner = false;
}
AutoPtr<T>& operator=(AutoPtr<T>& ap)
{
if (this != &ap)
{
if (_ptr != NULL)
{
delete _ptr;
}
_ptr = ap._ptr;
ap._owner = false;
}
return *this;
}
~AutoPtr()
{
if (_owner&&_ptr != NULL)
{
delete _ptr;
_ptr = NULL;
}
//因为类AutoPtr还要实现类似指针的功能,所以还要添加如下的简单指针的操作:
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
}
private:
T* _ptr;
bool _owner;
};
2、新版的AutoPtr
思想: 将第一个指向这块空间的指针直接置为空,然后析构
既然是拷贝构造函数和赋值运算度重载除了问题,好,那我给出来,看看还有什么问题。
template<class T>
class AutoPtr
{
public:
AutoPtr(T* ptr) //构造
:_ptr(ptr)
{}
~AutoPtr() //析构
{
if (_ptr != NULL)
{
delete _ptr;
}
}
AutoPtr<T>(AutoPtr<T>& ap) //拷贝构造
: _ptr(ap._ptr)
{
ap._ptr = NULL;
}
AutoPtr<T>& operator=(AutoPtr<T>& ap) //赋值运算符重载
{
if (this != &ap)
{
if (_ptr != NULL)
{
delete _ptr;
}
_ptr = ap._ptr;
ap._ptr = NULL;
}
}
//添加指针的一些功能
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return this->_ptr;
}
T* GetC()
{
return _ptr;
}
private:
T* _ptr;
};
现在就是一个基本可以使用的AutoPtr智能指针了。
需要提醒的是:
尽量不要使用 AutoPtr 这个指针,因为每次使用前面共同管理的一块空间的对象时,会使程序崩溃(对象已经析构了,呵呵)