码迷,mamicode.com
首页 > 其他好文 > 详细

智能指针简单实现

时间:2016-09-06 23:33:23      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:智能指针简单实现

   很多人都误以为智能指针是一个指针,其实不然,智能指针不是指针,智能指针是一个模板,由智能指针实例化出来的的对象具有和常规指针相似的行为,但是他能够自动的释放所指向的对象,所以我们称之为智能指针。如果我们用普通指针来创建一个指向某个对象的指针,那么我们最后必须要手动释放这块空间,而智能指针它是一个类,它释放空间是通过析构函数完成的,正是由于有了这一层封装机制,所以智能指针才能够管理一个对象的生命周期。(定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。这样的方法称为RAII)


  起初在C++标准库里面是没有智能指针的,直到C++11中才加入了shared_ptr和unique_ptr,weak_ptr。最早的智能指针在Boost库里面,Boost是为C++标准库提供扩展的一些C++程序的总称,由Boost社区组织开发维护。


1、auto_ptr

   auto_ptr在STL中早就存在了,auto_ptr是通过权限转移的方式来防止值拷贝所带来问题,所谓权限转移就是说开辟的动态内存任何时刻只能由一个指针指向。

技术分享


下面通过实现自己的AutoPtr来剖析一下auto_ptr。现在已经不用aotu_ptr了,常用的是scoped_ptr和shared_ptr.


<span style="font-size:14px;">template<typename T>
class AutoPtr                       //AutoPtr是一个类模板,不是指针类型
{
public:
       AutoPtr(T* ptr=0);
       AutoPtr(AutoPtr<T>& ap);
       AutoPtr<T>& operator=(AutoPtr<T>& ap);
       T* Get();
       T* Release();
       void Reset(T* ptr=0);
       T& operator*();
       T* operator->();
       ~AutoPtr();
private:
       T* _ptr;
};
template<typename T>
T* AutoPtr<T>::Get()
{
       return _ptr;
}
template<typename T>
T* AutoPtr<T>::Release()
{
       T* tmp = _ptr;
       _ptr = NULL;
       return tmp;
}
template<typename T>
void AutoPtr<T>::Reset(T* ptr = 0)
{
       delete _ptr;
       _ptr = ptr;
       ptr = NULL;
}
template<typename T>
AutoPtr<T>::AutoPtr(T* ptr=0)
:_ptr(ptr){}
template<typename T>
AutoPtr<T>::AutoPtr(AutoPtr<T>& ap)        //auto_ptr采用权限转移的方式,确保始终只有一个指针指向这块空间
{
       _ptr = ap._ptr;
       ap._ptr = NULL;          //权限转移
}
template<typename T>
AutoPtr<T>& AutoPtr<T>::operator=(AutoPtr<T>& ap)
{
       delete _ptr;
       _ptr = ap._ptr;
       ap._ptr = NULL;           //权限转移
       return *this;
}
template<typename T>
T& AutoPtr<T>::operator*()
{
       return *_ptr;
}
template<typename T>
T* AutoPtr<T>::operator->()          //有特殊处理
{
       return _ptr;
}
template<typename T>
AutoPtr<T>::~AutoPtr()
{
       if (_ptr != NULL)
       {
              delete _ptr;
              _ptr = NULL;
       }
}</span><span style="font-size: 19px;">
</span>



下面我们先来介绍boost库中的几种常用的智能指针,由于boost库不是C++标准库,所以我们在使用boost中的智能指针之前先要下载一个boost库,并把它包含到C++标准库中。


1、scoped_ptr

  由于auto_ptr的行为与真正的指针有很大区别,尤其是权限转移这种方法。为了防止值拷贝带来的问题,所以scoped_ptr从根本上就不允许拷贝和赋值(防赋值、防拷贝)。


template<typename T>
class ScopedPtr   //防拷贝,防赋值,使得scopedptr看起来更像一个指针类型,但实际上scopedptr是一个类模板
{
public:
       explicit ScopedPtr(T* ptr);
       T& operator*();
       T* operator->();
       ~ScopedPtr();
       T* Get() const;
       void Reset(T *p=0);
       void Swap(ScopedPtr<T>& sp);
protected:
       ScopedPtr(const ScopedPtr<T>& sp);                         //将拷贝和赋值运算符声明为保护,防赋值、防拷贝
       ScopedPtr<T>& operator=(const ScopedPtr<T>& ap);
private:
       T* _ptr;
};
template<typename T>
T* ScopedPtr<T>::Get() const
{
       return _ptr;
}
template<typename T>
void ScopedPtr<T>::Reset(T *p = 0)
{
       delete _ptr;
       _ptr = p;
       p = NULL;
}
template<typename T>
void ScopedPtr<T>::Swap(ScopedPtr<T>& sp)
{
       swap(_ptr,sp._ptr);
}
template<typename T>
ScopedPtr<T>::ScopedPtr(T* ptr)
:_ptr(ptr)
{}
template<typename T>
T& ScopedPtr<T>::operator*()
{
       return *_ptr;
}
template<typename T>
T* ScopedPtr<T>::operator->()           //有特殊处理
{
       return _ptr;
}
template<typename T>
ScopedPtr<T>::~ScopedPtr()
{
       if (NULL!= _ptr)
       {
              delete _ptr;
              _ptr =NULL;
       }
}



2、scoped_array

scoped_array是用来管理数组的。


<span style="font-size:14px;">template<typename T>
class ScopedArray
{
public:
       ScopedArray(T* ptr);
       ~ScopedArray();
       T& operator[](size_t index);
       void Reset(T* ptr=0);
       T* Get() const;
protected:
       ScopedArray(const ScopedArray<T>&);
       ScopedArray<T>& operator=(const ScopedArray<T>&);
private:
       T* _ptr;
};
template<typename T>
void ScopedArray<T>::Reset(T* ptr = 0)
{
       if (_ptr != ptr||_ptr==NULL)
       {
              delete[] _ptr;
              _ptr = ptr;
              ptr = NULL;
       }
}
template<typename T>
T* ScopedArray<T>::Get() const
{
       return _ptr;
}
template<typename T>
ScopedArray<T>::ScopedArray(T* ptr)
:_ptr(ptr)
{}
template<typename T>
ScopedArray<T>::~ScopedArray()
{
       if (NULL != _ptr)
       {
              delete[] _ptr;
              _ptr = NULL;
       }
}
template<typename T>
T& ScopedArray<T>::operator[](size_t index)
{
       return _ptr[index];
}</span><span style="font-size: 24px;">
</span>



3、shared_ptr

  shared_ptr允许拷贝和赋值,其底层实现是以"引用计数"为基础的,通过引用计数来控制空间的释放,当一块空间创建时引用计数为1,当有新的指针指向这块空间时,引用计数加1,反之减1,直到引用计数减为0时才真的释放这块空间。所以说shared_ptr更像一个指针。


template<typename T>
class SharedPtr            //采用引用计数,实现一个可以有多个指针指向同一块内存的类模板,SharedPtr是类模板,不是智能指针类型
{
public:
       SharedPtr(T* ptr);
       SharedPtr(const SharedPtr<T>& sp);
       SharedPtr<T>& operator=(SharedPtr<T> sp);
       T& operator*();
       T* operator->();
       ~SharedPtr();
       int Count()
       {
              return *_pCount;
       }
private:
       void Release()
       {
              if (--(*_pCount) == 0)
              {
                     delete _ptr;
                     delete _pCount;
                     _ptr = NULL;
                     _pCount = NULL;
              }
       }
private:
       T* _ptr;
       int* _pCount;             //指向引用计数的空间
};
template<typename T>
SharedPtr<T>::SharedPtr(T* ptr)
:_ptr(ptr)
, _pCount(new int(1)){}
template<typename T>
SharedPtr<T>::SharedPtr(const SharedPtr<T>& sp)
{
       _ptr = sp._ptr;
       _pCount= sp._pCount;
       ++(*_pCount);
}
template<typename T>
SharedPtr<T>& SharedPtr<T>::operator=(SharedPtr<T> sp)
{
       std::swap(sp._ptr,_ptr);
       std::swap(sp._pCount,_pCount);
       return *this;
}
template<typename T>
T& SharedPtr<T>::operator*()
{
       return *_ptr;
}
template<typename T>
T* SharedPtr<T>::operator->()
{
       return _ptr;
}
template<typename T>
SharedPtr<T>::~SharedPtr()
{
       Release();
}



4、shared_array

shared_array也是管理数组的。


<span style="font-size:14px;">template<typename T>
class SharedArray
{
public:
       SharedArray(T* ptr);
       ~SharedArray();
       SharedArray(const SharedArray<T>& sp);
       SharedArray<T>& operator=(SharedArray<T> sp);
       T& operator[](size_t index);
private:
       T* _ptr;
       int* _pCount;
};
template<typename T>
SharedArray<T>::SharedArray(T* ptr)
:_ptr(ptr)
, _pCount(new int(1))
{}
template<typename T>
SharedArray<T>::~SharedArray()
{
       if (--(*_pCount) == 0)
       {
              delete[] _ptr;
              _ptr = NULL;
              delete _pCount;
              _pCount = NULL;
       }
}
template<typename T>
SharedArray<T>::SharedArray(const SharedArray<T>& sp)
{
       _ptr = sp._ptr;
       _pCount = sp._pCount;
       ++*pCount;
}
template<typename T>
SharedArray<T>& SharedArray<T>::operator=(SharedArray<T> sp)
{
       swap(_ptr,sp._ptr);
       swap(_pCount,sp._pCount);
       return *this;
}
template<typename T>
T& SharedArray<T>::operator[](size_t index)
{
       return _ptr[index];
}</span><span style="font-size: 24px;">
</span>



本文出自 “11132019” 博客,转载请与作者联系!

智能指针简单实现

标签:智能指针简单实现

原文地址:http://11142019.blog.51cto.com/11132019/1846846

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!