为了进行高效对象复制操作而引入句柄类,从内容上来说,句柄是包含单一对象的容器。为了使句柄拥有类似于类指针的作用但是避免类指针的不安全性等缺陷,不允许句柄对->操作符进行定义。为了实现多个句柄捆绑统一对象和安全的销毁操作引入引用计数的概念。进行引用计数相关操作的抽象类称作计数类。
计数类包含以下要点:
构造函数能够立即绑定句柄,从而引用计数在构造成功的时候就是1;
折构函数能够递减引用计数,计数值为0时销毁对象指针。
一个典型的计数类:
- class UseCount{
- int *p;
- public:
- UseCount:p(new int(1)){}
- UseCount(const UseCount&);
- UseCount& operator=(const UseCount&);
- ~UseCount(){if(--*p==0)delete p;}
- bool only(){return *p==1;}
- };
一个典型的句柄:
- class Handle{
- public:
- //some code
- private:
- UseCount u;
- Someclass p;
- };
Someclass为该句柄捆绑的类。
-----------------------分割线---------------------
PART II.写时复制
这种通过改变句柄捆绑的对象进行的复制会面临一种问题,例如:
Someclass temp;
handle(t,temp);
handle t2=t;
这时如果处理t2捆绑的对象, t捆绑的对象当然也会变化,但这个不是我们希望的结果,在这种情况下必须进行的复制也就是写时复制,当对象的值改变时必须进行对象的拷贝。
写时复制的思路是,写以前判断该对象是不是捆绑有唯一句柄,如果不是,通过递减引用计数进行复制和分配句柄。
-------------------分割线--------------------------
练习:利用一个基类打印四则运算算式,算式在main中控制。
代码:
- #include <iostream>
- using namespace std;
- class expr;
- class expr_node
- {
- friend ostream& operator<<(ostream&,const expr&);
- friend class expr;
- int use;//引用计数
- protected:
- expr_node():use(1){}//构造函数
- virtual void print(ostream&)const=0;
- virtual ~expr_node(){}
- };
- class expr
- {
- friend ostream& operator<<(ostream&,const expr&);
- expr_node* p;
- public:
- expr(int);
- expr(const string&,expr);
- expr(const string&,expr,expr);
- expr(const expr&);
- expr& operator=(const expr&);
- ~expr(){if(--p->use==0)delete p;}
- };
- class int_node:public expr_node
- {
- friend class expr;
- int n;
- public:
- int_node(int k):n(k){}
- void print(ostream& o)const{o<<n;}
- };
- class unary_node:public expr_node
- {
- friend class expr;
- string temp;
- expr opnd;
- unary_node(const string& a,expr t):temp(a),opnd(t){}
- void print(ostream& o)const{o<<"("<<temp<<opnd<<")";}
- };
- class binary_node:public expr_node
- {
- friend class expr;
- string temp;
- expr opndA,opndB;
- binary_node(const string& a,expr t1,expr t2):temp(a),opndA(t1),opndB(t2){}
- void print(ostream& o)const{o<<"("<< opndA<<temp<< opndB<<")";}
- };
- expr::expr(int n){p=new int_node(n);}
- expr::expr(const string& a,expr t){p=new unary_node(a,t);}
- expr::expr(const string& a,expr t1,expr t2){p=new binary_node(a,t1,t2);}
- expr::expr(const expr& t){p=t.p; ++p->use;}
- expr& expr::operator=(const expr& rhs)
- {
- rhs.p->use++;
- if(--p->use==0)
- delete p;
- p=rhs.p;
- return *this;
- };
- ostream& operator<<(ostream& o,const expr& t)
- {
- t.p->print(o);
- return o;
- };
- int main()
- {
- expr t = expr("*", expr("-", 5), expr("+", 3, 4));
- cout<<t<<endl;
- t=expr("*",t,t);
- cout<<t<<endl;
- }