您的位置:首页 > 编程语言 > C语言/C++

c++基于引用计数的智能指针实现

2014-06-10 18:09 323 查看
引用计数指针(Reference CountedPointer)是为了解决C++必须为使用new申请的指针进行delete操作从而防止内存泄露而提出的。在C++中,new和delete必须成对出现,否则会导致内存泄露或错误。以前在写C++程序的时候,成天提心吊胆,生怕由于这个原因出现什么错误。有时候也在想,有没有一种方法,可以使编写C++程序像编写Java或者C#程序那样安心。

 

当然,遇到这种困扰的人不止我一个,在我之前就有许多前辈思考并尝试解决这个问题。引用计数指针就是其中的一种解决方案。引用计数指针的思想非常简单,就是为类的每个对象都增加一个计数器变量,每当该对象被赋值给一个不同的引用计数指针时时,计数器就会自动加1,当这个引用计数指针被析构的时候,计数器就会自动减1,当计数器减到0时,说明这个对象已经不再被使用,于是将这个对象释放。

 

许多开源的项目中都有用到这种方法。比如,irrlicht游戏引擎和Nebula 3游戏引擎中都能看到这种方法的影子。基于Nebula 3游戏引擎中的代码,我自己重新整理实现了一份代码。文章的最后给出了下载链接。

 

在使用的时候,只需令希望使用引用计数指针的类继承ReferenceCounter类即可,然后用new关键字声明该类的对象指针,并将这个指针赋值给一个RefCountedPointer<>对象。但是,这里有一点需要注意的是,继承了ReferenceCounter的类就不能再多重继承其他实类了,否则将无法正确释放对象的空间。例如,

1 classCDerivation : public CBase, public ReferenceCounter
2 {
3   ...
4 };

 

如果其中CBase是一个实类,那么,这样的代码是不允许的,Debug的时候,要释放空间的地址并不是CDerivation对象的地址,而是ReferenceCounter对象地址相对于CDerivation对象的地址的偏移地址。为了解决这个问题,可以令基类继承自ReferenceCounter类,其他派生类继承基类的同时也就继承了ReferenceCounter类。例如,

1 classCBase : public ReferenceCounter
2 {
3   ...
4 };
5 classCDerivation : public CBase
6 {
7   ...
8 };
9  

 

注意,上面所说的是不能多重继承其他实类,如果一个类想使用引用计数指针,并且除了继承ReferenceCounter类以外,继承的其他类都是接口(就是只包含纯虚函数、静态常量和静态常量,且不包含任何其他成员变量或函数的类,这种接口的概念与Java和C#中接口的概念几乎相同),那么,这种多重继承是允许的。例如,

 1 #include <iostream>
2  using namespace std;
3
4 #include "RefCountedPointer.h"
5 #include "ReferenceCounter.h"
6
7  struct IInterfaceA
8 {
9 static int IA;
10 virtual void displayA(void)= 0;
11 virtual void displayB(void)= 0;
12 };
13
14  int IInterfaceA::IA = 100;
15
16  struct IInterfaceB
17 {
18 static int IB;
19 virtual void displayC(void)= 0;
20 virtual void displayD(void)= 0;
21 };
22
23  int IInterfaceB::IB = 102;
24
25  class CClass : publicReferenceCounter, public IInterfaceA, public IInterfaceB
26 {
27 public:
28 int a;
29 int b;
30 int c;
31 int d;
32 public:
33 virtual void displayA(void)
34 {
35 cout<<a;
36 }
37
38 virtual void displayB(void)
39 {
40 cout<<b;
41 }
42
43 virtual void displayC(void)
44 {
45 cout<<c;
46 }
47
48 virtual void displayD(void)
49 {
50 cout<<d;
51 }
52 };
53
54 void main(void)
55 {
56 RefCountedPointer<CClass> p = new CClass;
57 p->a = 0;
58 p->b = 1;
59 p->c = 2;
60 p->d = 3;
61
62 p->displayA();
63 cout<<endl;
64 p->displayB();
65 cout<<endl;
66 p->displayC();
67 cout<<endl;
68 p->displayD();
69 cout<<endl;
70 }

 

好了就写到这吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: