首页 > 代码库 > C++——几种简单的智能指针

C++——几种简单的智能指针

最简单的智能指针就是将指针封装在类里,同时将该类的复制与赋值禁用,也就是使该类失去值语义。

实现代码如下:

 1 #ifndef SMART_PTR_H 2 #define SMART_PTR_H 3 #include <iostream> 4  5  6 template <typename T> 7 class SmartPtr 8 { 9 public:10     typedef T          value_type;11     typedef T*        pointer;12     typedef T&        reference;13 14     SmartPtr(T *ptr = NULL)15         :_ptr(ptr)16     { }17 18     ~SmartPtr() { delete _ptr; }19 20     reference operator* () const throw()21     { return *_ptr; }22 23     pointer operator-> () const throw()24     { return _ptr; }25     26 private:27     SmartPtr(const SmartPtr &);28     void operator=(const SmartPtr &);29 30     pointer _ptr;31 };32 33 #endif  /*SMART_PTR_H*/
View Code

 

 

相对于这种最简单的智能指针,我们还可以实现一种具有复制与赋值功能的智能指针——auto_ptr。

实现代码如下:

 1 #ifndef AUTO_PTR_H 2 #define AUTO_PTR_H 3 #include <iostream> 4  5 template <typename T> 6 class AutoPtr 7 { 8 public: 9     typedef T     value_type;10     typedef T*    pointer;11     typedef T&    reference;12 13 14     AutoPtr(T *ptr = NULL);15     AutoPtr(AutoPtr &other);16     ~AutoPtr();17     AutoPtr &operator= (AutoPtr &other) throw();18 19     reference operator*() const throw()20     { return *_ptr; }21 22     pointer operator->() const throw()23     { return _ptr; }24 25     void reset(T *ptr = NULL) throw()26     {27         if(_ptr != ptr)28         {29             delete _ptr;30             _ptr = ptr;31         }32     }33 34     pointer release() throw()35     {36         pointer tmp(_ptr);37         _ptr = NULL;38         return tmp;39     }40 41     operator bool() throw() { return _ptr != NULL; }42 43 private:44     value_type *_ptr;45 };46 47 48 template <typename T>49 AutoPtr<T>::AutoPtr(T *ptr)50     :_ptr(ptr)51 {52 53 }54 55 template <typename T>56 AutoPtr<T>::AutoPtr(AutoPtr<T> &other)57     :_ptr(other._ptr)58 {59     other._ptr = NULL;60 }61 62 template <typename T>63 AutoPtr<T>::~AutoPtr()64 {65     delete _ptr;66 }67 68 template <typename T>69 AutoPtr<T> &AutoPtr<T>::operator= (AutoPtr<T> &other) throw()70 {71     reset(other.release());72 73     return *this;74 }75 #endif  /*AUTO_PTR_H*/
View Code

在使用AutoPtr时,我们需要注意:

  1.AutoPtr的复制与赋值会引发控制权的转移,这是一种转移语义。

  2.不要使用AutoPtr,尤其是与容器结合。

  3.在AutoPtr中,我们提供了一种转化,将该类可转化为bool型。

 

对于智能指针来说,比较常用的一种实现方法是使用引用计数,创建新的对象时,我们将计数器count初始化为1,每次复制该对象或将该对象赋值给其他对象时,计数器count加1,析构的时候将计数器减1,当计数器为0时,我们才真正删除该对象内的指针。

具体实现代码如下:

 

 1 #ifndef COUNT_PTR_H 2 #define COUNT_PTR_H 3 #include <iostream> 4  5  6 template <typename T> 7 class CountPtr 8 { 9 public:10     typedef T                 value_type;11     typedef T*                pointer;12     typedef T&                reference;13 14 15     explicit CountPtr(T *p = NULL);16     CountPtr(const CountPtr<T> &other);17     ~CountPtr();18 19     CountPtr<T> &operator= (const CountPtr<T> &other);20     reference operator*() const throw() { return *_ptr; }21 22     pointer operator->() const throw() { return _ptr; }23 24     size_t count() const throw() { return *_count; }25 26     void swap(CountPtr<T> &other) throw()27     {28         std::swap(_ptr, other._ptr);29         std::swap(_count, other._count);30     }31 32     void reset(T *ptr = NULL) throw()33     {34         dispose();35 36         _ptr = ptr;37         _count = new size_t(1);38     }39 40 41     pointer get() const throw() { return _ptr; }42 43     bool unique() const throw() { return *_count == 1; }44 45     operator bool() { return _ptr != NULL; }46 private:47 48     void dispose()49     {50         if(-- *_count == 0)51         {52             delete _ptr;53             delete _count;54         }55     }56 57     T *_ptr;58     size_t *_count;59 60 };61 62 template <typename T>63 CountPtr<T>::CountPtr(T *p)64     :_ptr(p),65      _count(new size_t(1))66 {67 68 }69 70 template <typename T>71 CountPtr<T>::~CountPtr()72 {73     dispose();74 }75 76 template <typename T>77 CountPtr<T>::CountPtr(const CountPtr<T> &other)78     :_ptr(other._ptr),79      _count(other._count)80 {81     ++ (*_count);82 }83 84 template <typename T>85 CountPtr<T> &CountPtr<T>::operator= (const CountPtr<T> &other)86 {87     ++(*other._count);            //先++防止自身赋值失败88 89     dispose();90 91     _ptr = other._ptr;92     _count = other._count;93 94     return *this;95 }96 #endif  /*COUNT_PTR_H*/
View Code

在引用计数智能指针中,需要注意:
  1.计数器count采用指针,这样每个指针共享一个计数。

  2.析构时,仅将引用计数减1,只有当计数为0时,才释放资源。

  3.复制指针时,计数将加1.

  4.赋值时,可以先对other的计数加1,来避免处理自我赋值。

 

使用引用计数指针,可以将失去值语义的对象放入容器中。

 

C++——几种简单的智能指针