为什么需要智能指针
是因为我们在没有使用智能指针之前都是使用原生态的指针来管理资源,程序在退出时,原生态的指针不会自动的去释放资源,而c++中还没有支持垃圾回收机制,资源需要用户自己手动进行释放,这就可能由于用户的操作导致内存泄漏,因此用户在写代码时必须要谨慎。
什么是内存泄露,内存泄露的危害
什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不
是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而
造成了内存的浪费。
内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会
导致响应越来越慢,最终卡死。
智能指针的使用以及原理
RAII的思想
是一种
利用对象生命周期来控制程序资源
(如内存、文件句
柄、网络连接、互斥量等等)的简单技术。
在对象构造时获取资源
,接着控制对资源的访问使之在对象的生命周期内始终保持有效,
最后在对象析构的
时候释放资源
。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
- 不需要显式地释放资源。
- 采用这种方式,对象所需的资源在其生命期内始终保持有效
smart_ptr
template<class T>
class smart_ptr
{
public:
// RAII的思想来管理资源,好处:该资源不用手动释放
/*
缺陷:当使用一个smart_ptr对象构造一个新的对象时或者 两个对象在赋值时
而该类的拷贝构造函数和赋值运算符重载没有实现,那么编译器按照浅拷贝的方式自己生成
*/
smart_ptr(T* ptr = nullptr)
:_ptr(ptr)
{}
~smart_ptr()
{
if(_ptr)
{
delete _ptr;
}
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
private:
T* _ptr;
};
缺陷:当使用一个smart_ptr对象构造一个新的对象时或者 两个对象在赋值时
而该类的拷贝构造函数和赋值运算符重载没有实现,那么编译器按照浅拷贝的方式自己生成
auto_ptr
auto_ptr
的实现原理:管理权转移的思想,
namespace bite
{
/*
缺陷:不能同时访问一份资源
会造成野指针,很严重
*/
template<class T>
class auto_ptr
{
public:
auto_ptr(T* ptr)
:_ptr(ptr)
,_owner(false)
{
if(_ptr)
_owner = true;
}
~auto_ptr()
{
if(_ptr && _owner)
{
delete _ptr;
_owner = false;
}
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
// 解决浅拷贝问题:采用资源的转移方式来解决问题
// 让一个对象拥有资源
auto_ptr(auto_ptr<T>& ap)
:_ptr(ap._ptr)
,_owner(ap._owner)
{
ap._owner = false;
}
auto_ptr<T>& operator=(auto_ptr<T>& ap)
{
if(this!=&ap)
{
// 当前对象本身管理资源了,那么将资源释放
if(_ptr && _owner)
delete _ptr;
_ptr = ap._ptr;
_owner = ap._owner;
ap._owner = false;
}
return *this;
}
private:
T* _ptr;
bool _owner; // false 当前对象没有权力释放资源
};
}
缺陷:不能同时访问一份资源
会造成野指针,很严重
由于野指针的问题,所以auto_ptr被禁止使用
unique_ptr
unique_ptr
的实现原理:简单粗暴的防拷贝
// unique——ptr 对象资源独占,不在共享
template<class T>
class unique_ptr
{
public:
unique_ptr(T* ptr = nullptr)
:_ptr(ptr)
{}
~unique_ptr()
{
if(_ptr)
{
delete _ptr;
}
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
// 解决浅拷贝问题
unique_ptr(const unique_ptr<T>&) = delete;
unique_ptr<T>& operator=(const unique_ptr<T>&) =delete;
private:
T* _ptr;
};
C++11中提供了更加可靠的并且支持拷贝的shared_ptr