RAII:资源分配及初始化。但是这个翻译并没有显示出这个惯用法的真正内涵.RAII的好处在于它提供了一种资源自动管理的方式,当出现异常,回滚等现象时,RAII可以正确的释放资源。
内存泄漏会导致:
,,,,,,1.内存耗尽2。其他程序可能用不了3了。程序崩溃
在资源的获取和释放之间,我们通常会使用资源,但常常一些不可预计的异常会在资源使用过程中产生,这就使资源没有得到正确的释放。但是我们其实是可以捕捉异常的,但是捕捉异常会使得代码冗余杂乱,量大而且可读性比较低。
比如:
void DoSomething () { ,,,int * p=new int (1); ,,,cout<& lt;“DoSomething () & lt; & lt; endl; } void 测试() { ,,试一试 ,,{ ,,,,,DoSomething (); ,,} ,才能赶上(…) ,,{ ,,,,,delete p; ,,,,,扔; ,,} }
这样短短一个代码看起来却很杂乱,而且也不好控制。
所以我们引出了智能指针。智能指针的实现原理就是RAII。
下面介绍几个提高库中的智能指针。
- <李>
AutoPtr
李>AutoPtr的实现主要是管理权转移。它没有考虑引用计数,当用一个对象构造另一个对象时,会转移这种拥有关系。
templateclass AutoPtr {//friend ostream&, operator<& lt;, & lt; T> (ostream&,操作系统,,const AutoPtr ,,美联社); 公众: AutoPtr (T *, ptr) :_ptr (ptr) {} ~ AutoPtr () { if (_ptr !=NULL) { delete _ptr; } } AutoPtr (AutoPtr ,,美联社) :_ptr (ap._ptr) { 时间=ap._ptr 零; } 公众: AutoPtr ,,操作符=(const AutoPtr< T>,,美联社) { if (却;能够!=,美联社) { delete _ptr; 时间=_ptr ap._ptr; 时间=ap._ptr 零; return _ptr; } } T&,操作符* () { return * _ptr; } T *,运营商→() { return _ptr; } 公众: T *, GetPtr () { return _ptr; } 私人: T *, _ptr; };
旧版的AutoPtr在它的成员函数中有一个变量所有者,在构架对象的时候所有者为真的。当用它去构建新的对象时,他自己的主人变为假,新对象的所有者为真的。赋值重载的时候也是,新对象的主人是真的。这样在析构的时候只要判断所有者的状态是否为真,当为真时,将这块空间删除即可。
templateclass AutoPtr { 公众: AutoPtr (T *, ptr) :_ptr (ptr) ,老板(真正的) {} ~ AutoPtr () { if (所有者) { delete _ptr; } } AutoPtr (AutoPtr ,,美联社) :_ptr (ap._ptr) ,老板(真正的) { 时间=ap._ptr 零; 时间=ap.owner 假; } 公众: AutoPtr ,,操作符=(const AutoPtr< T>,,美联社) { if (却;能够!=,美联社) { delete _ptr; 时间=_ptr ap._ptr; 时间=ap.owner 假; 时间=owner 真实; return _ptr; } } }
看起来旧的比新的好.AutoPtr最大的缺点就是只能有一个指针管理一块空间,那么为什么新的还取代了旧的呢?看下面
AutoPtr, ap1 (new int (1)); , ,if (1) , ,{ , AutoPtr<才能;int>, ap2 (ap1); , ,} ,=,* ap1 3;
2。ScopePtr//守卫指针
这个类型的指针简单来说就是简单粗暴的防拷贝。
templateclass ScopedPtr { 公众: ScopedPtr (T *, ptr) :_ptr (ptr) {} ~ ScopedPtr () { if (_ptr !=, NULL) { delete _ptr; } } 保护: ScopedPtr (const ScopedPtr ,, sp); ScopedPtr ,,操作符=(ScopedPtr ,, sp); 公众: T&,操作符* () { return * _ptr; } T *,运营商→() { return _ptr; } 私人: T *, _ptr; };
将拷贝构造函数和赋值重载函数只声明不实现,而且是保护。就是为了防止在类外实现的情况发生,简单粗暴哈哈。