在我们编写大型工程时,用new动态申请内存时,必须要用delete去释放。但若是出现异常时,我们不能保证申请的内存都被释放,这时我们需要一个在适当的时候自动释放的指针。这里我们引入智能指针。
智能指针:
(1)智能指针不是指针,而是一个类。类里封装了能够完成资源初始化的构造函数,析构函数完成对资源的释放。(这种思想方法称为RAII:资源分配及初始化)
(2) 智能指针是存储指向动态分配对象指针的类。除了能够在适当的时候自动删除指向的对象,其工作机制很像C++内置指针。在出现异常时,能保证正确的销毁动态分配对象,其也可以用于跟踪被多用户共享的动态分配对象。
(3)智能指针大部分用于生存期控制,阶段控制。在类内部重载operator*和operator->让智能指针看起来像是原生指针。
//重载operator* 普通指针使用 *p1=20 为让智能指针看起来与普通指针一样
T&operator*()
{
return *_ptr;
}
//重载operator-> 普通指针使用p1->fun() 调用函数,
T*operator->()
{
return _ptr;
}
这里我们主要看下auto_ptr
auto_ptr:(管理权转移)
1 auto_ptr是C++标准可提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者,当auto_ptr对象的生命周期结束时,其析构函数会将auto_ptr对象拥有的动态内存自动释放。即时发生异常,通过异常的栈展开过程也能将动态内存释放,auto_ptr不支持new数组。
2 包含头文件: #include<memory>
3 auto_ptr实现方法
(1)构造函数
用已经存在的指向动态内存的指针来构 造
int *p=new int(10);
auto_ptr<int> sp(p);
直接构造自能指针:
auto_ptr<int>sp(new int (10))
(2)拷贝构造函数:利用已经存在的智能指针拷贝构造出新的智能指针
(3)赋值
(4)operator*() 和operator->()
模拟实现auto_ptr代码:
#include<iostream>
using namespace std;
template<class T>
class AutoPtr
{
public:
//构造函数
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
{
//cout << "AutoPtr()" << endl;
}
//拷贝构造函数 ap2(ap1)
AutoPtr(AutoPtr<T>& ap)
:_ptr(ap._ptr)
{
//管理权转移,只有一个指针指向动态内存
ap._ptr = NULL;
cout << "AutoPtr(AutoPtr<T>& ap)" << endl;
}
//赋值运算符 ap2=ap3
AutoPtr<T>& operator=(AutoPtr<T>& ap)
{
if (this != &ap)
{
delete this->_ptr;
_ptr = ap._ptr;
ap._ptr = NULL;
}
//cout << "AutoPtr<T>& operator=(AutoPtr<T>& ap) " << endl;
return *this;
}
//对operator* 进行重载
T& operator*()
{
return *_ptr;
}
//对operator->进行重载
T* operator->()
{
return _ptr;
}
//析构函数
~AutoPtr()
{
if (_ptr)
{
cout << _ptr << endl;
delete _ptr;
_ptr = NULL;
//cout << "~AutoPtr()" << endl;
}
}
protected:
T* _ptr;
};