浅析智能指针(一)

来源:互联网 发布:淘宝影响二次销售规则 编辑:程序博客网 时间:2024/05/16 08:46

一.什么是智能指针

       所谓智能指针就是智能/自动化的管理指针所指向的动态资源的释放。实际上智能指针是一种抽象数据类型,行为表现的像一个指针。通过重载“->”和“*”,就可以像使用指针一样来使用智能指针;而智能指针又是如何来管理指针指向对象的释放问题呢?其实这是RAII的一种应用。RAII(Resource acquisition is initialization),即资源分配即初始化。定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放 。那么有了指针我们为什么还需要智能指针呢?接下来看下边的例子。

#include <iostream>#include <string>using namespace std;void Fun(){string* p1 = new string("hello");bool IsEnd = true;if (IsEnd){throw 1;delete p1;}delete p1;}int main(){try{Fun();}catch (int e){cout << e << endl;}return 0;}

这段代码看起来好像没什么问题,但其实隐藏了一个非常重要的错误--内存泄漏。但是从哪泄漏的呢?那就要从抛出异常说起了,在上述代码中,异常被抛出后,是在main函数中捕获的,但是Fun函数中的p1并没有被释放,所以造成内存泄漏。所以,这时候就需要智能指针,能够自动的帮我们释放空间。

二、智能指针的发展

智能指针的发展可以简单的分为三个阶段:

(1)auto_ptr    c++98/03 

(2)scoped_ptr/shared_ptr/week_ptr    boost

(3)unique_ptr/shared_ptr/week_ptr   c++11

auto_ptr 的本质是管理权的转移,带有缺陷的设计,一般不建议使用。scope_ptr/unique_ptr是防拷贝,功能不全。shared_ptr是通过引用计数来解决空间释放问题,功能强大,但是有时候会存在循环引用的问题,这时候就需要配合week_ptr来解决这个问题


首先来说说aotu_ptr,我们先看下边一段代码:

template<typename T>class AutoPtr{public:AutoPtr(T* ptr = NULL):_ptr(ptr){}AutoPtr(AutoPtr<T>& ap)//管理权的转移{this->_ptr = ap._ptr;ap._ptr = NULL;}//s2=s1,先将s2释放掉,再将s1赋给s2,将s1置空AutoPtr<T>& operator=(AutoPtr<T>& ap){if (this != &ap){delete this->_ptr;this->_ptr = ap._ptr;ap._ptr = NULL;}return *this;}T& operator*()//   *的重载{return *_ptr;}T& operator->()//  ->的重载{return _ptr;}    ~AutoPtr()    {delete _ptr;    }void Reset(T* ptr = NULL)//赋空{if (_ptr != ptr){delete _ptr;}_ptr = ptr;}protected:T* _ptr;};

对于内置类型来说,两个指针是可以同时指向同一块空间的,并且通过这个指针对该空间进行操作是不会出现问题。但在自定义类型中,两个指针指向同一块空间会产生问题。管理权的转移就是一种解决办法。在拷贝构造和运算符重载的时候会发生管理权的转移,我们的目的是通过拷贝构造,让两个智能指针管理同一个对象。如果用默认的拷贝构造函数就会产生浅拷贝问题,两个指针指向同一个对象在进行析构的时候,这块空间会被释放两次,就会出现内存错误。所以,一个简单的办法,就是让原来的那个指针放弃对该空间的操作权限,所以实际上只有一个指针起作用。同时,这也是auto_ptrd的一个缺陷。
管理权转移的步骤如下:












0 0
原创粉丝点击