标签:智能指针 raii
讲这个之前,先来看一个例子:
void Test1 () { int* p1 = new int(2); //... try { DoSomeThing(); } catch(...) { delete p1 ; throw; } //... delete p1 ; }
这个例子,是通过C++异常处理机制,来管理动态开辟出来的内存,这是可以做到的。那如果我们以后new出来一块内存,都要这么做,那么代码量将会相当的大,有时候逻辑也会理不清楚,也显得非常繁琐,那C++为了处理这个问题,提出了一个叫RAII(Resource Acquisition Is Initialization)的东东。
RAII:资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。这个类具体到下面的智能指针。
智能指针:所谓智能指针就是智能\自动化管理动态开辟内存的释放。
在C++11之前,标准库中,只有一个auto_ptr,下面是模拟实现auto_ptr旧版本.
/*旧版本*/ /*实现原理:通过拥有者的改变来最后确定是否析构对象*/ #include <iostream> using namespace std; template<class T> class AutoPtr { public: AutoPtr(T* ptr) :_ptr(ptr) { _owner = true; } AutoPtr(AutoPtr<T>& ap) :_ptr(ap._ptr),_owner(ap._owner) { ap._owner = false; } AutoPtr<T>& operator=(AutoPtr<T>& ap) { if(this != &ap) { if(_owner) { delete _ptr; } _ptr = ap._ptr; _owner = ap._owner; if(ap._owner) { ap._owner = false; } } return *this; } ~AutoPtr() { if(_owner) { delete _ptr; } } public: T& operator*() { return *_str; } T* operator ->() { return _str; } private: T* _ptr; bool _owner; }; void Test1() { AutoPtr<int> ap1(new int(1)); AutoPtr<int> ap2(ap1); AutoPtr<int> ap3(new int(3)); ap3 = ap2; } int main() { Test1(); return 0; }
显示结果:
这样看结果是对的,但是看下面这个Test2()
void Test2() { AutoPtr<int> ap1(new int(1)); AutoPtr<int> ap2(ap1); AutoPtr<int> ap3(new int(3)); AutoPtr<int> ap4(ap3); ap4 = ap1; }
显示结果:
看上面就出现问题了,你把ap1 赋给 ap4 ,但是ap4的_owner 是 false ,这就是有问题的。到最后,ap4只是指向共有的那块空间而已,没有达到真正的管理,再看Test3()
void Test3() { AutoPtr<int> ap1(new int(1)); if(1) { AutoPtr<int> ap2(ap1); } *ap1 = 10; }
显示结果:
程序直接崩溃了,因为产生了野指针的访问,访问的那一块空间已经释放了,所以就会崩溃了,正是由于旧版本有这诸多的问题,C++改进了一下他,使他变得很“强大”,下来看模拟实现:
/*新版本*/ /*实现原理:管理权的转交*/ #include <iostream> using namespace std; template <class T> class AutoPtr { public: AutoPtr(T* str) :_str(str) {} AutoPtr(AutoPtr<T>& ap) :_str(ap._str) { ap._str = NULL; } AutoPtr<T>& operator=(AutoPtr<T>& ap) { if(this != &ap) { delete _str; _str = ap._str; ap._str = NULL; } return *this; } ~AutoPtr() { if(_str) delete _str; } public: T& operator*() { return *_str; } T* operator ->() { return _str; } private: T* _str; }; struct A { int _a; }; void Test4() { AutoPtr<int>ap(new int(1)); AutoPtr<int>ap2(ap); AutoPtr<int>ap3(new int(2)); AutoPtr<int>ap4(ap3); ap4 = ap; } int main() { Test4(); return 0; }
显示结果:
当然这个结果是正确的,但是你要这个AutoPtr又有什么用,你用对象之间拷贝构造新对象和对象之间相互赋值时,就是为了让他们共同管理,但是现在,这就有点low了,既没有达到那种共同管理,也在拷贝构造对象和相互赋值时,不清不楚,所以他很low.当然有些技术大牛早就看这个不顺眼了,于是自己弄出来既可以解决自动管理内存的释放,也可以用对象之间拷贝构造新对象和对象之间相互赋值,达到你想要的那种效果,没毛病,待续...
本文出自 “Pzd流川枫” 博客,请务必保留此出处http://xujiafan.blog.51cto.com/10778767/1761067
标签:智能指针 raii
原文地址:http://xujiafan.blog.51cto.com/10778767/1761067