智能指针的原理和简单实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能指针的原理和简单实现相关的知识,希望对你有一定的参考价值。

  1. 什么是智能指针?

    智能指针实质上是一个类,定义一个类来封装资源的分配和释放。这个类的构造函数中传入一个指针,完成资源的分配和初始化。在析构函数中释放传入的该指针,完成资源的释放。

  2. 为什么要用智能指针?

    智能指针就是智能,自动化的管理指针所指向的动态资源。

    例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露。

// case1
void Test2()
{
 int* p1 = new int(2);
 bool isEnd = true;
 //...
 if (isEnd)
 {
  delete p1;
  return;
 }
 //...
 delete p1;
}
// case2
void DoSomeThing()
{
 //...
 throw 2;
 //...
}
void Test2()
{
 int* p1 = new int(2);
 //...
 try {
  DoSomeThing();
 }
 catch (...)
 {
  delete p1;
  throw;
 }
 //...
 delete p1;
}

  • 智能指针的简单实现。

    Auto_ptr:不能共享所有权,只要出现两个指针指向同一块资源,就释放前一个指针的管理权。保证只有一个指针指向一块资源。

    Scoped_ptr:将类中的成员函数拷贝构造和赋值运算符只申明为protected,不定义。所以不可能有两个指针指向同一个对象。

    Shared_ptr:采用引用计数的方法。将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针。

    ScopedArray和Scoped_ptr类似,只是操作的是数组。SharedArray同理。

     

template <class T>
class AutoPtr
{
public:
 AutoPtr(T*ptr)
  :_ptr(ptr)
 {}
 AutoPtr( AutoPtr<T>&ap)
  :_ptr(ap._ptr)
 {
  ap._ptr = NULL;
 }
 AutoPtr<T>&operator=(const AutoPtr<T>&ap)
 {
  if (this != &ap)
  {
   delete _ptr;
   _ptr = ap._ptr;
   ap._ptr = NULL;
  }
 }
 ~AutoPtr()
 {
  if (_ptr)
  {
   delete _ptr;
   _ptr = NULL;
  }
 }
 
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:
 T*_ptr;
};
struct Node
{
 int _data;
 Node*_next;
};
void Test_AutoPtr()
{
 int*p1 = new int(2);
 int*p2 = p1;
 int*p3 = p2;
 *p3 = 10;
 delete p1;
 AutoPtr<int>ap1(new int(2));
 AutoPtr<int>ap2=ap1;     //此时ap1为NULL,无管理权
 AutoPtr<int>ap3(ap2);
                         //此时ap2为NULL,无管理权
 //*ap2 = 10;            //程序崩溃    
 *ap3 = 10;
 AutoPtr<Node>sp1(new Node);
 sp1->_data = 10;
}
template<class T>
class ScopedPtr
{
public:
 ScopedPtr(T*ptr)
  :_ptr(ptr)
 {}
 
 ~ScopedPtr()
 {
  if (_ptr)
  {
   delete _ptr;
   _ptr = NULL;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:                    //只申明,不定义,防止拷贝构造和赋值运算符重载。
 ScopedPtr(const ScopedPtr<T>&sp);   //保护,防止在外定义。若写为public,则有可能在类外定义。
 ScopedPtr<T>& operator=(const ScopedPtr<T>&sp);
protected:
 T*_ptr;
};
void Test_ScopedPtr()
{
 ScopedPtr<int>sp1(new int(3));
 //ScopedPtr<int>sp2(sp1);             //protectd:无法访问
}
template <class T>
class ScopedArray
{
public:
 ScopedArray(T*ptr)
  :_ptr(ptr)
 {}
 
 ~ScopedArray()
 {
  if (_ptr)
  {
   delete[]_ptr;
  }
 }
 T&operator[](size_t Index)
 {
  return _ptr[Index];
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
protected:
 ScopedArray(const ScopedArray<T>&sp);
 ScopedArray<T>&operator=(const ScopedArray<T>&sp);
protected:
 T*_ptr;
};
void Test_ScopedArray()
{
 ScopedArray<int>sp1(new int[5]);
 //ScopedPtr<int>sp2(sp1);
 
}
template <class T>
class SharedPtr
{
public:
 SharedPtr(T*ptr)
  :_ptr(ptr)
  , _Pcount(new long(1))
 {}
 SharedPtr(const SharedPtr<T>&sp)
  :_ptr(sp._ptr)
  , _Pcount(sp._Pcount)
 {
  ++*(_Pcount);
 }
 //SharedPtr<T>&operator=(const SharedPtr<T>&sp)    //传统写法
 //{
 // if (this != &sp)
 // {
 //  if (--(*_Pcount) == 0)
 //  {
 //   delete _ptr;
 //   delete _Pcount;
 //  }
 //  _ptr = sp._ptr;
 //  _Pcount = sp._Pcount;
 //  ++(*_Pcount);
 // }
 // return *this;
 //}
 SharedPtr<T>&operator=(const SharedPtr<T>sp)     //现代写法
 {
  swap(_ptr, sp._ptr);
  swap(_Pcount, sp._Pcount);
  return *this;
 }
 ~SharedPtr()
 {
  if (--(*_Pcount) == 0)
  {
   delete _ptr;
   delete _Pcount;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
 long GetCount()
 {
  return *_Pcount;
 }
protected:
 T*_ptr;
 long*_Pcount;
};
void Test_SharedPtr()
{
 SharedPtr<int>sp1(new int(2));
 SharedPtr<int>sp2(sp1);
}
template <class T>
class SharedArray
{
public:
 SharedArray(T*ptr)
  :_ptr(ptr)
  , _Pcount(new long (1))
 {}
 SharedArray(const SharedArray<T>&sp)
  :_ptr(sp._ptr)
  , _Pcount(sp._Pcount)
 {
  ++*(_Pcount);
 }
 SharedArray<T>&operator=(const SharedArray<T>sp)     //现代写法
 {
  swap(_ptr, sp._ptr);
  swap(_Pcount, sp._Pcount);
  return *this;
 }
 ~SharedArray()
 {
  if (--(*_Pcount) == 0)
  {
   delete[] _ptr;
   delete _Pcount;
  }
 }
 T&operator*()
 {
  return *_ptr;
 }
 T*operator->()
 {
  return _ptr;
 }
 T*GetPtr()
 {
  return _ptr;
 }
 T&operator[](size_t Index)
 {
     return _ptr[Index];
 }
 long GetCount()
 {
  return *_Pcount;
 }
protected:
 T*_ptr;
 long*_Pcount;
};
void Test_SharedArray()
{
 SharedArray<int>sp1(new int[5]);
 SharedArray<int>sp2(sp1);
}

本文出自 “printf的返回值” 博客,请务必保留此出处http://10741125.blog.51cto.com/10731125/1782624

以上是关于智能指针的原理和简单实现的主要内容,如果未能解决你的问题,请参考以下文章

智能指针基本原理,简单实现,常见问题

智能指针的简单实现

智能指针的原理和实现

智能指针的原理和实现

智能指针原理及实现- shared_ptr

shared_ptr智能指针模板类的简单实现(c++11)