智能指针
为什么要有智能指针?
下面我们先分析一下下面这段程序有没有什么内存方面的问题?提示一下:注意分析MergeSort函数中的问题。
void MergeSort(int* a, int n) {
int* tmp = (int*)malloc(sizeof(int)*n);
_MergeSort(a, 0, n - 1, tmp);
// 这里假设处理了一些其他逻辑
vector<int> v(1000000000, 10);
// ...
// free(tmp);
}
问题分析:上面的问题分析出来我们发现有以下两个问题?
- malloc出来的空间,没有进行释放,存在内存泄漏的问题。
- 异常安全问题。如果在malloc和free之间如果存在抛异常,那么还是有内存泄漏。这种问题就叫异常安全。
智能指针的使用及原理
RAII
RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。
在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
- 不需要显式地释放资源。
- 采用这种方式,对象所需的资源在其生命期内始终保持有效。
// 使用RAII思想设计的SmartPtr类
template<class T>
class SmartPtr {
public:
SmartPtr(T* ptr = nullptr)
: _ptr(ptr)
{
}
~SmartPtr()
{
if(_ptr)
delete _ptr;
}
private:
T* _ptr;
};
void MergeSort(int* a, int n) {
int* tmp = (int*)malloc(sizeof(int)*n);
SmartPtr<int> sp(tmp);
// _MergeSort(a, 0, n - 1, tmp);
// 这里假设处理了一些其他逻辑
vector<int> v(1000000000, 10);
// ...
}
智能指针的原理
述的SmartPtr还不能将其称为智能指针,因为它还不具有指针的行为。指针可以解引用,也可以通过->去访问所指空间中的内容,因此:AutoPtr模板类中还得需要将* 、->重载下,才可让其像指针一样去使用。
template<class T>
class SmartPtr {
public:
SmartPtr(T* ptr = nullptr)
: _ptr(ptr)
{
}
~SmartPtr()
{
if(_ptr)
delete _ptr;
}
T& operator*() {
return *_ptr;}
T* operator->() {
return _ptr;}
private:
T* _ptr;
};
struct Date
{
int _year;
int _month;
int _day;
}
int main()
{
SmartPtr<int> sp1(new int);
*sp1 = 10
cout<<*sp1<<endl;
SmartPtr<int> sparray(new Date);
sparray->_year = 2018;
sparray->_month = 1;