我们使用 new关键字 或者 malloc函数 开辟一块空间时,因为这块空间是在堆上开辟的,如果不手动释放,即便出了作用域,这块空间也依然存在,这个时候就会造成内存泄漏。
为了保证资源的释放,我们可以使用智能指针。其实就是资源管理权限的转移,不想手动释放,交给一个对象管理,对象什么时候被销毁,这块资源也就什么时候被释放。
目录
1、RAII特性
RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句 柄、网络连接、互斥量等等)的简单技术。
这种特性的关键在于构造函数和析构函数:
- 构造函数:获取资源。比如拿到动态开辟的空间地址
- 析构函数:对象出了作用域,会自动调用析构函数,可以在析构函数中释放这块资源
其实我们就是把这块资源的管理权转交给了一个对象,这种方式的好处是无需显式释放资源,资源在对象的生命周期内一直有效。
2、智能指针的底层实现
智能指针就是借用了 RAII 特性,只不过为了让其具备指针的行为,需要重载 * 、-> 两个运算符,让其像指针一样使用。
(1) RAII特性实现
RAII的特性主要体现在构造函数和析构函数,下面我们实现一个SmartPtr类
template<class T>
class SmartPtr
{
public:
SmartPtr(T* ptr)
:_ptr(ptr) // 获取资源
{}
~SmartPtr() {
if (_ptr)
{
delete _ptr; // 释放资源
_ptr = nullptr;
}
}
private:
T* _ptr;
};
(2) *、-> 运算符重载
// 重载运算符 *
T& operator*() {
return *_ptr;
}
// 重载运算符 ->
T* operator->() {
return _ptr;
}
3、智能指针的使用
上述实现的只是智能指针最简单的功能,使用方法和标准库的智能指针类似。关于unique_ptr 和 shared_ptr,放在其他地方介绍。
int main()
{
int* p1 = new int;
SmartPtr<int> sptr(p1); // 上述自定义的SmartPtr
unique_ptr<int> up(new int); // 标准库中的unique_ptr
shared_ptr<int> sp(new int); // 标准库中的shared_ptr
return 0;
}