引用计数的智能指针的实现

引用计数的智能指针是对《Effective C++ 条款13:以对象管理资源》的一个实现。

我们要设计一个智能指针,使他能够管理资源,在正确的实际调用资源的析构函数。

首先我们需要一个指针reference来指向资源,当智能指针构造时,用reference指针指向资源,在我们确定资源应该被析构时,我们对reference指针进行delete。

如果只有reference指针的话,只能实现出auto_ptr的效果,我们还需要添加引用计数系统counter来统计指向资源的智能指针的个数。counter不可以是一个普通的int型变量,因为不同的智能指针可能会有相同的计数,也不可以是一个static变量,因为同时存在的智能指针可以指向不同的资源,也就拥有不同的引用计数。因此将counter设计成一个指向int的指针,指向相同资源的智能指针的counter也指向相同的int值,这样对counter做修改时,就会影响到所有拥有这个counter的智能指针。

我们的智能指针还应该能实现多态的效果,因此指向同一个资源的智能指针中的reference指针可能有不同的类型。然而这就给我们的析构过程带来了困扰,我们在析构资源的时候需要知道资源原始的类型与指针,因此我们用一个指向void*的指针originalReference来保存原始的指针。

有了指向原始资源的指针,我们还需要原始资源的类型才能正常delete,我们在每个资源创建出来时,提供一个指向特殊的销毁函数的指针originalDestructor,保证这个函数能够成功的销毁资源。

有了这些成员变量我们就可以实现出一个简单的引用计数的智能指针。可见智能指针占用的空间要比普通指针大数倍。

按照《条款14:在资源管理类中小心copying行为》,仔细的为智能指针添加copying行为。

最后适当的重载操作符,使智能指针能够像一个普通指针那样使用。

  1 namespace cylib {
  2
  3     // 引用计数操作器
  4     template<typename T> struct ReferenceCounterOperator
  5     {
  6         // 返回一个引用计数器
  7         static int* CreateCounter(T* reference)
  8         {
  9             return new int(0);
 10
 11         }
 12         // 删除引用函数
 13         static void DeleteReference(int* counter, void* reference)
 14         {
 15             delete counter;// 删除计数器
 16             delete (T*)reference;// 删除资源
 17         }
 18     };
 19
 20
 21     // 智能指针类
 22     template<typename T> class SmartPtr
 23     {
 24     private:
 25         template<typename X> friend class SmartPtr;
 26         // 删除器
 27         typedef void (*Destructor)(int*, void*);
 28         // 引用计数器
 29         int* counter;
 30         // 引用资源,在拷贝过程中可能改变类型
 31         T* reference;
 32         // 原始引用资源,保持资源第一次创建时的指针
 33         void* originalReference;
 34         // 原始资源删除函数,在最后一个引用被析构时调用,删除资源
 35         Destructor originalDestructor;
 36
 37         // 增加引用计数
 38         void Inc()
 39         {
 40             if (counter)
 41             {
 42                 ++(*counter);
 43             }
 44         }
 45         // 减少引用计数,如果资源不再被引用则删除资源
 46         void Dec()
 47         {
 48             if (counter)
 49             {
 50                 if (--(*counter) == 0)
 51                 {
 52                     originalDestructor(counter, originalReference);
 53                     counter = 0;
 54                     reference = 0;
 55                     originalReference = 0;
 56                     originalDestructor = 0;
 57                 }
 58             }
 59         }
 60
 61         // 返回当前计数器
 62         int* Counter() const
 63         {
 64             return counter;
 65         }
 66
 67         // 私有构造器
 68         SmartPtr(int* _counter, T* _reference, void* _originalReference, Destructor _originalDestructor)
 69             : counter(_counter)
 70             , reference(_reference)
 71             , originalReference(_originalReference)
 72             , originalDestructor(_originalDestructor)
 73         {
 74             Inc();
 75         }
 76
 77     public:
 78         // 获取资源的直接指针
 79         T* get() const
 80         {
 81             return reference;
 82         }
 83         // 重载->操作符
 84         T* operator->()const
 85         {
 86             return reference;
 87         }
 88         // 重载*操作符,危险!
 89         T& operator*() const {
 90             return *reference;
 91         }
 92
 93         // 构造一个空的智能指针,不指向任何资源
 94         SmartPtr()
 95             : counter(0)
 96             , reference(0)
 97             , originalReference(0)
 98             , originalDestructor(0)
 99         {}
100         // 用一个普通指针构造智能指针,是最基本的用法
101         SmartPtr(T* pointer)
102             : counter(0)
103             , reference(0)
104             , originalReference(0)
105             , originalDestructor(0)
106         {
107             if (pointer)
108             {
109                 counter = ReferenceCounterOperator<T>::CreateCounter(pointer);// 创建新的计数器
110                 reference = pointer;// 获取当前资源的引用
111                 originalReference = pointer;// 将原始资源置为当前资源
112                 originalDestructor = ReferenceCounterOperator<T>::DeleteReference;// 连接删除器
113                 Inc();// 引用计数增加
114             }
115         };
116         // 用另一个同类型的智能指针进行拷贝构造,不创建新资源
117         SmartPtr(const SmartPtr<T>& pointer)
118             : counter(pointer.counter)
119             , reference(pointer.reference)
120             , originalReference(pointer.originalReference)
121             , originalDestructor(pointer.originalDestructor)
122         {
123             Inc();// 引用计数增加
124         }
125         // 用其他类型的智能指针进行转型拷贝构造,不创建新资源
126         // 将原始类型U转换为当前智能指针的类型T,但是原始资源与原始删除器不变
127         template<typename U> SmartPtr(const SmartPtr<U>& pointer)
128             : counter(0)
129             , reference(0)
130             , originalReference(0)
131             , originalDestructor(0)
132         {
133             T* converted = pointer.get();
134             if (converted)
135             {
136                 counter = pointer.Counter();
137                 reference = converted;
138                 originalReference = pointer.originalReference;
139                 originalDestructor = pointer.originalDestructor;
140                 Inc();
141             }
142         }
143
144         // 析构当前的智能指针,减少引用计数
145         ~SmartPtr()
146         {
147             Dec();
148         }
149
150         // 将一个普通指针的值赋给智能指针
151         // 智能指针之前引用的资源取消,由普通指针构造出新的智能指针
152         // 构造失败则将智能指针置为空
153         SmartPtr<T>& operator=(T* pointer)
154         {
155             Dec();// 原本的资源引用减少
156             if (pointer)
157             {
158                 counter = ReferenceCounterOperator<T>::CreateCounter(pointer);
159                 reference = pointer;
160                 originalReference = pointer;
161                 originalDestructor = &ReferenceCounterOperator<T>::DeleteReference;
162                 Inc();
163             }
164             else
165             {
166                 counter = 0;
167                 reference = 0;
168                 originalReference = 0;
169                 originalDestructor = 0;
170             }
171             return *this;
172         }
173         // 将另一个智能指针的值赋给自身
174         // 智能指针之前引用的资源取消,并引用新的智能指针的资源
175         SmartPtr<T>& operator=(const SmartPtr<T>& pointer)
176         {
177             if (this != &pointer)// 判断是否自赋值
178             {
179                 Dec();
180                 counter = pointer.counter;
181                 reference = pointer.reference;
182                 originalReference = pointer.originalReference;
183                 originalDestructor = pointer.originalDestructor;
184                 Inc();
185             }
186             return *this;
187         }
188         // 将一个不同类型的智能指针赋给自身
189         // 智能指针之前引用的资源取消,并引用新的智能指针的资源
190         // 转型失败的话返回空智能指针
191         template<typename U> SmartPtr<T>& operator=(const SmartPtr<U>& pointer)
192         {
193             T* converted = pointer.get();
194             Dec();
195             if (converted)
196             {
197                 counter = pointer.counter;
198                 reference = converted;
199                 originalReference = pointer.originalReference;
200                 originalDestructor = pointer.originalDestructor;
201                 Inc();
202             }
203             else
204             {
205                 counter = 0;
206                 reference = 0;
207                 originalReference = 0;
208                 originalDestructor = 0;
209             }
210             return *this;
211         }
212
213         // 重载比较操作符,用于比较智能指针与普通指针是否指向相同资源
214         bool operator==(const T* pointer)const { return reference == pointer; }
215         bool operator!=(const T* pointer)const { return reference != pointer; }
216         bool operator>(const T* pointer)const { return reference>pointer; }
217         bool operator>=(const T* pointer)const { return reference >= pointer; }
218         bool operator<(const T* pointer)const { return reference<pointer; }
219         bool operator<=(const T* pointer)const { return reference <= pointer; }
220
221         // 重载比较操作符,用于比较两个智能指针是否指向相同资源
222         bool operator==(const SmartPtr<T>& pointer)const { return reference == pointer.reference; }
223         bool operator!=(const SmartPtr<T>& pointer)const { return reference != pointer.reference; }
224         bool operator>(const SmartPtr<T>& pointer)const { return reference>pointer.reference; }
225         bool operator>=(const SmartPtr<T>& pointer)const { return reference >= pointer.reference; }
226         bool operator<(const SmartPtr<T>& pointer)const { return reference<pointer.reference; }
227         bool operator<=(const SmartPtr<T>& pointer)const { return reference <= pointer.reference; }
228
229         // 智能指针指向非空时有true的布尔值
230         operator bool()const{ return reference != 0; }
231
232     };
233
234 }

测试代码:

 1 #include <iostream>
 2 #include "SmartPoint.h"
 3 using namespace std;
 4
 5 class B {
 6 public:
 7     B() { cout << "构造了一个基类~" << endl; }
 8     virtual ~B() { cout << "基类被析构啦!" << endl; }
 9     virtual void message() { cout << "基基基基基基基基基基基基" << endl; }
10 };
11
12 class D : public B {
13 public:
14     D() { cout << "构造了一个派生类~" << endl; }
15     virtual ~D() { cout << "派生类被析构啦!" << endl; }
16     virtual void message() { cout << "派派派派派派派派派派派派" << endl; }
17 };
18
19 void test1() {
20     cout << "构造演示:" << endl;
21     cylib::SmartPtr<B> bp = new B();
22     cylib::SmartPtr<B> bp2(new B());
23 }
24 void test2() {
25     cout << "比较演示:" << endl;
26     cylib::SmartPtr<B> bp = new B();
27     B* p = bp.get();
28     cylib::SmartPtr<B> bp2 = bp;
29     if (bp == p) cout << "相等" << endl;
30     if (bp == bp2) cout << "相等" << endl;
31 }
32 void test3() {
33     cout << "多态演示:" << endl;
34     cylib::SmartPtr<B> bp;
35     cylib::SmartPtr<D> dp = new D();
36     bp = dp;
37     bp->message();
38 }
39
40
41 int main()
42 {
43     cout << "---------------" << endl;
44     test1();
45     cout << "---------------" << endl;
46     test2();
47     cout << "---------------" << endl;
48     test3();
49     cout << "---------------" << endl;
50     system("pause");
51
52 }

测试结果:

 1 ---------------
 2 构造演示:
 3 构造了一个基类~
 4 构造了一个基类~
 5 基类被析构啦!
 6 基类被析构啦!
 7 ---------------
 8 比较演示:
 9 构造了一个基类~
10 相等
11 相等
12 基类被析构啦!
13 ---------------
14 多态演示:
15 构造了一个基类~
16 构造了一个派生类~
17 派派派派派派派派派派派派
18 派生类被析构啦!
19 基类被析构啦!
20 ---------------
21 请按任意键继续. . .
时间: 2025-01-01 12:59:56

引用计数的智能指针的实现的相关文章

基于引用计数的智能指针

编程语言中实现自动垃圾回收机制方式有好几种,常见的有标记清除,引用计数,分代回收等. C++需要手动管理垃圾,可以自己实现一个智能指针.最简单的是引用计数的思路 template <class T> class SmartPointer { T* obj; unsigned int* count; SmartPointer(T* ptr) { obj = ptr; count = new int; *count = 1; } SmartPointer(SmartPointer &p)

引用计数智能指针

<a>C++ <span style="font-family:宋体;">智能指针具体解释</span></a> 一.简单介绍 因为 C++ 语言没有自己主动内存回收机制.程序猿每次 new 出来的内存都要手动 delete. 程序猿忘记 delete.流程太复杂.终于导致没有 delete.异常导致程序过早退出,没有运行 delete 的情况并不罕见. 用智能指针便能够有效缓解这类问题,本文主要解说參见的智能指针的使用方法.包含:std

c++智能指针以及循环引用问题(转)

解决循环引用: 在知道存在循环引用的条件下,使用boost::weak_ptr,即弱引用来代替循环引用中的某个强引用,从而打破循环引用的环. 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,比如流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见,并造成内存泄露.如此c++引入 智能指针 . c++ 智能指针主要包括:unique_ptr,shared_ptr, weak_ptr, 这三种,其中auto

Android的引用计数(强弱指针)技术及一些问题

Android C++框架层的引用计数技术 C++中对指针的使用时很头疼的事情,一个是经常会忘记free 指针,造成内存泄露,另外一个就是野指针问题:访问已经free掉的指针.程序debug工作的相当大部分,都是花费在这.Android中通过引用计数来自动管理指针的生命周期,动态申请的内存将会在不再需要时被自动释放(有点类似Java的垃圾回收),不用程序员明确使用delete来释放对象,也不需要考虑一个对象是否已经在其它地方被释放了,从而使程序编写工作减轻不少,而程序的稳定性也大大提高. And

循环引用-智能指针的死穴之一

智能指针的实现思路也体现了C++基于对象的原则,对象应该为自己管理的资源负责,包括资源的分配与释放,而且最好将资源的释放与分配搞的自动化一点,典型的实现方法就是在构造函数里分配资源,在析构函数里释放资源,这样当其他程序员在使用这个对象时,该对象的资源问题几乎不用额外的操心,即优雅又方便 然后如此完美的东西,也有其不容忽视的地方,直接上代码: // share_ptr.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "c

boost智能指针使用

#include <iostream> #include <tr1/memory> #include <boost/scoped_ptr.hpp> //scoped_ptr还不属于tr1 #include <boost/scoped_array.hpp> //scored_array也不属于tr1 #include <boost/shared_array.hpp> //shared_array也不属于tr1 class CTest { publi

C++智能指针类模板

1.智能指针本质上是一个对象,这个对象可以像原生的一样来进行使用.原因是智能指针对象对应的类中,将指针相关的操作都进行了重载操作处理,所以才会达到这种像是原生的效果. 2.智能指针的意义: 现在C++开发库中最重要的类模板之一 C++中自动内存管理的主要手段 能够在很大程度上避开内存相关的问题 3.在QT中开发库中也提供了智能指针类模板,在STL标准库中也提供了,在c++的标准库忘了什么名了中也提供了智能指针类模板.所以智能指针类模板在C++中的地位很重要 4.STL中的智能指针类模板 auto

使用智能指针来管理对象 (基于RAII)

////一个简单的防止内存泄露的例子//void test() { //使用RAII的特性管理资源 //当智能指针unique_ptr被销毁时,它指向的对象也将被销毁 //这里test函数返回后 p将自动销毁 //unique_ptr<int[]> p( new int[200] ); //直接生成资源 //test函数返回后 p不能被正常销毁,就会造成资源泄露 //int* p = new int[200]; } int main() { while( 1 ) { test(); Sleep

Boost智能指针-基础篇

简介 内存管理一直是 C++ 一个比较繁琐的问题,而智能指针却可以很好的解决这个问题,在初始化时就已经预定了删除,排解了后顾之忧.1998年修订的第一版C++标准只提供了一种智能指针:std::auto_ptr(现以废弃),它基本上就像是个普通的指针:通过地址来访问一个动态分配的对象.std::auto_ptr之所以被看作是智能指针,是因为它会在析构的时候调用delete操作符来自动释放所包含的对象.当然这要求在初始化的时候,传给它一个由new操作符返回的对象的地址.既然std::auto_pt