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,来避免处理自我赋值。

 

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

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。