为什么要使用智能指针?
因为在C++中没有自动的回收机制,在每次new开辟新的空间以后,就要用delete来对开辟的空间进行释放。在代码比较多的时候,很有可能出现忘记deleted释放,这让就会出现内存泄漏。在一段进行了try/catch的代码段里面,即使你写入了delete,也有可能因为发生异常,程序进入catch块,从而忘记释放内存,造成内存泄漏。
智能指针可以有效的避免这个问题。智能指针的实质是一个对象,但是表现的行为确实指针。遵循RAII的规则(RAII,也称为“资源获取就是初始化”,是c++等编程语言常用的管理资源、避免内存泄露的方法。它保证在任何情况下,使用对象时先构造对象,最后析构对象。)。
常见的几种智能指针:
- auto_ptr 管理权转移,带有缺陷的设计,会释放一个空间多次,造成内存泄漏。
模拟实现auto_ptr
template<class T>
class AutoPtr
{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
{}
AutoPtr(AutoPtr<T>& ap)//拷贝构造函数
:_ptr(ap._ptr)
{
ap._ptr = NULL;
}
AutoPtr<T>& operator = (AutoPtr<T>& ap)//赋值运算符重载
{
if (this != &ap)
{
delete _ptr;
_ptr = ap._ptr;
ap._ptr = NULL;//管理权转移
}
return *this;
}
~AutoPtr()//析构
{
if (_ptr)
{
cout << _ptr << endl;
delete _ptr;
_ptr = NULL;
}
}
T& operator*()
{
return *_ptr;
}
T& operator->()
{
return _ptr;
}
protected:
T* _ptr;
};
int main()
{
AutoPtr<int> ap1(new int(1));
AutoPtr<int> ap2 = ap1;//ap2(ap1)error
//ap1地址指向随机
AutoPtr<int> ap3(new int(2));
ap2 = ap3;//ap3地址为随机值
system("pause\n");
return 0;
}
//auto_ptr会使原来的数据丢失,所以不建议使用。
- scoped_ptr 防拷贝,高效,简洁。不需要拷贝/赋值的时候使用。在使用的时候,对赋值、拷贝操作只声明不定义。
模拟实现scoped_ptr:
template<class T>
class ScopedPtr
{
public:
//RAII
ScopedPtr(T* ptr = NULL)
:_ptr(ptr){}
~ScopedPtr()
{
if (_ptr)
{
delete _ptr;
}
}
T& operator*()
{
return *_ptr;
}
T& operator->()
{
return _ptr;
}
protected:
T* _ptr;
private://只声明不定义,且声明为私有
ScopedPtr(const ScopedPtr<T>& sp);
ScopedPtr<T>& operator = (const ScopedPtr<T>&);
};
int main()
{
ScopedPtr<int> sp1(new int(3));
//ScopedPtr<int> sp2(sp1);//错误
return 0;
}
- share_ptr 共享(引用计数)管理,支持赋值/拷贝。缺陷是循环引用,使用weak_ptr能辅助的解决这个问题。
模拟实现share_ptr:
template<class T>
struct Delete //清理单个空间
{
void operator()(T* ptr)//定制删除器(仿函数)
{
delete ptr;
}
};
template<class T>
class DeletArray//清理数组
{
public:
void operator()(T* ptr)
{
delete[] ptr;
}
};
template<class T,class D = Delete<T>>//默认是delete,不是delete[]
class SharedPtr
{
public:
SharedPtr(T *ptr)
:_ptr(ptr)
, _countRef(new int(1)){}
SharedPtr<T,D>& operator= (const SharedPtr<T,D>& sp)//赋值运算符的重载
{
if (_ptr != sp._ptr)
{
Release();
_ptr = sp._ptr;
_countRef = sp._countRef;
++(*_countRef);
}
return *this;
}
SharedPtr(const SharedPtr<T, D>& sp)//拷贝构造
:_ptr(sp._ptr)
, _countRef(sp._countRef)
{
++(*_countRef);
}
inline void Release()
{
if (--(*_countRef) == 0)
{
cout << _ptr << endl;
_del( _ptr);
delete _countRef;
}
}
~SharedPtr()
{
Release();
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
int UseCount()//引用计数
{
return *_countRef;
}
protected:
T* _ptr;
int* _countRef;//引用计数
D _del;//定制的仿函数删除器
};