智能指针: 所谓智能指针就是智能/⾃动化的管理指针所指向的动态资源的释放 为什么我们会有智能指针呢,我们通过下面的代码来看一下
void DoSomeThing () { throw 2 ; } void Test2 () { int* p1 = new int(2); try { DoSomeThing(); } catch(...) { throw; } delete p1 ; }我们下来可以尝试一下这个程序,尝试过的同学会知道这个程序在调试中没有报错,但是在运行的时候就会崩溃,那么这个是什么原因呢? 原因是我们在开辟了空间遇到了异常,throw是抛出异常,我们都知道在抛出异常后面的代码都不会继续执行,所以这里我们的错误在于没有释放空间
这里我们就要使用智能指针首先我们介绍一下 智能指针是一个模版类 它的目的: 1,管理指针指向对象的释放间隔 2,可以像指针一样用起来(这里我们会用到重载)
我们先说一下RAII RAII(Resource Acquisition Is Initialization) 资源分配即初始化,定义⼀个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。
下来我们来模拟实现一下AutoPtr
template<class T> class AutoPtr { public: AutoPtr(T *ptr) :_ptr(ptr) T& operator*() { return *_ptr; } T *operator->() { return _ptr; } ~AutoPtr() { delete _ptr; } protected: T *ptr; };总结AutoPtr: 1,管理指针指向对象的释放 PAII——>(自动)析构函数释放管理对象 2,operator*,operator->的重载让我们像原生指针一样使用智能指针访问管理对象
但是同时它也是有缺点的
AutoPtr<int>ap1(new int); AutoPtr<int>ap2(ap1);我们会发现同一块内存释放了两次,程序挂了(解决方法:管理员的转移,但是这个是有问题的) 在这里AutoPtr用了管理员转移的方法来解决问题
AutoPtr(AutoPtr<T>& ap) { //管理权的转移 this->_ptr=ap._ptr; ap._ptr=NULL; }但是对于管理权的转移这种方法是存在缺陷的,我们尽量不要使用
下来我们引用了ScopedPtr 它的特点是简单粗暴——防拷贝(只声明不定义)
下来我们来模拟实现一下ScopedPtr
template<class T> class ScopedPtr { public: ScopedPtr(T*_ptr) :_ptr(ptr) {} ~ScopedPtr() { delete _ptr; } T &operator*() { return *_ptr; } T*operator->() { return _ptr; } //我们把它声明为保护,是防止对它的调用 protected: ScopePtr(ScopePtr<T> & s); ScopedPtr<T> operator=(ScopedPtr<T>&s); protected: T*_ptr; }; protected: ScopePtr(ScopePtr<T> & s); ScopedPtr<T> operator=(ScopedPtr<T>&s); //对于这一块的代码,我们把它声明为保护,是防止对它的调用,也就是防拷贝 //防拷贝是只声明不定义,并且要声明为私有或者保护,避免别人对它调用。但是我们的ScopedPtr也是有缺陷的——功能不全
那么我们引入了share_ptr,在下一篇博客我们会模拟实现SharePtr.
