C++句柄类
来源:互联网 发布:混血 知乎 编辑:程序博客网 时间:2024/05/07 17:01
一直不能理解句柄类究竟有什么作用,尽管看到很多C++书籍中对句柄的使用进行了介绍。直到最近碰到一个问题才让我对句柄类的使用有了较为深入地了解。
这个问题简单来说是这样:设想一个类封装了一种数据结构,当我们声明该类的一个指针对象来指向这种数据结构的一块数据时,有两种情况:
1. 对数据块进行读取操作,并不改变数据的值
2. 对数据块进行改写操作,但要保留原数据块(因为其他地方要使用)
对于第一种情况,我们只需要构造一个类的指针对象,将他指向这个数据块。
对于第二种情况,问题有些不同。首先,需要在类的构造函数中重新申请内存将数据块拷贝过来,然后进行改写。但问题在于什么时候去申请新的数据块我们并不清楚。根据“写时复制”的原则,只有在我们需要改写数据块的时候才应该去重新申请内存。倘若一直没有对数据块进行改写,所有类的指针对象可以共享这个数据块中的内容。
这种内存管理的思想被许多程序框架使用,例如Qt中的隐式共享,在内容有变动的情况下才对的数据结构做复制,否则仅做共享。看一个例子:
QString str1 = "one"; //str1指向"one"QString str2 = str1; //str2没有改变"one",此时"one"被共享两次此时,指向"one"的计数器的值为2。现在,倘若我们改变str2指向的内容
str2 = "two"; //改变str2的内容str2指向了新的数据块,因此"one"的计数减为1,"two"计数变为1。此时在改变str1的值
str1 = str2;此时,"two"的计数增加到2,"one"计数变为0。这种对内存管理的方式可以用一个新的类来表示,这个类就是句柄。
简单来说,句柄就将指向数据的指针和该数据共享次数封装起来,我们直接看一个例子,假设有一个坐标类Point,建立一个Handle类来管理Point
Point类很简单,有两个成员(x,y)
class Handle;class Point{public:friend Handle;Point(int a=0, int b=0):x(a), y(b){};~Point();Point& operator =(const Point &rhs);public:int x;int y;};Point::~Point(){}Point& Point::operator =(const Point &rhs){ x = rhs.x+1; y = rhs.y+1; return *this;}句柄类
class Handle{public:Handle();Handle(int x, int y);Handle(const Point &Data);~Handle();Handle &operator =(const Handle &rhs);private:Point *data;int *num; //表示*data被共享的次数void destroy();};
Handle::Handle(){num = new int(1); data = new Point(); //缺省复制构造函数将Point初始化为远点坐标 }Handle::Handle(int x, int y){num = new int(1);data = new Point(x,y);}Handle::Handle(const Point &Data){num = new int(1);data = new Point(Data);}Handle::~Handle(){destroy();}void Handle::destroy(){if(--*num == 0) //如果指向数据的指针只有一个,则直接delete{ //因为如果改变data指向的数据,则指向这块数据的指针个数为0delete data;data = 0;delete num;num = 0;}}Handle &Handle::operator =(const Handle &rhs){(*rhs.num)++; //首先将右操作数的计数器加1,destroy(); data = rhs.data;num = rhs.num;return *this;}
int main(void){Handle h(1,1);Handle h1;Handle h2;std::cout<<"h.num = "<<*h.num<<" h1.num = "<<*h1.num<<" h2.num = "<<*h2.num<<std::endl; //三个对象引用计数都为1h1 = h; //指向h.data的引用计数变为2std::cout<<"h.num = "<<*h.num<<" h1.num = "<<*h1.num<<" h2.num = "<<*h2.num<<std::endl; h1 = h2; //指向h2.data的引用计数变为2,h.num减少为1std::cout<<"h.num = "<<*h.num<<" h1.num = "<<*h1.num<<" h2.num = "<<*h2.num<<std::endl;return 0; }打印结果
h.num = 1 h1.num = 1 h2.num = 1
h.num = 2 h1.num = 2 h2.num = 1
h.num = 1 h1.num = 2 h2.num = 2
这样就实现了写时复制和对指针的动态管理,节省了复制数据时的开销
0 0
- 【C++】浅谈C++句柄类
- c句柄
- c句柄
- [C/C++] Very very good !!! 句柄类
- C++_Primer 15.8 句柄类与继承
- c++句柄
- C++/MFC 句柄
- C 语言句柄handle
- C 句柄 回调
- [C++]什么是句柄?为什么会有句柄?
- 句柄类
- 句柄类
- 句柄类
- 句柄类
- 句柄类
- 句柄类
- 句柄类
- 句柄类
- iOS 远程通知
- POJ2486---Apple Tree
- [Bug Fix]Messy Audio语音电话不清晰问题
- 浮点运算是怎么实现的?
- 我的博客开始更新
- C++句柄类
- copy, retain, assign , readonly , readwrite,strong,weak,nonatomic整理
- 手机回声消除原理
- 霍夫曼编码
- 最大子列和问题(同时输出有最大和的子列的首尾元素)【数据结构测试1.2】
- 浅谈Android的四大组件的设计思路
- 浅谈Binder的基本原理
- 线程间通信
- MySQL_05-Select查询详解