《C++沉思录》笔记--句柄

句柄
从代理类我们继续考虑,怎样可以避免对象复制呢,引出句柄
Class Point{
public:
 Point():xval(0),yval(0){}
 Point(int x,int y):xval(x),yval(y){}
 int x() const{return xval;}
 int y() const{return yval;}
 Point& x(int xv){xval = xv;return *this;}
 Point& y(int yv){yval = yv;return *this;}
private:
 int xval,yval;
}

句柄是什么?我们希望
Point p;
Handle h(p);
是将h绑定到p上,但这里有管理和控制的问题,什么时候删除p呢
Class Handle{
public:
 Handle();
 Handle(int,int);
 Handle(const Point&);
 Handle(const Handle&);
 Handle& operate=(const Handle&);
 ~Handle();
 int x() const;
 Handle& x(int);
 int y() const;
 Handle& y(int);
}

允许多个句柄绑定到同一个对象上,则需要计数,但这个计数的属性不能是Handle类的,
因为如果这样,那减少一个应用要去修改其他句柄的计数。也不能是Point类的,因为这样就改了原来的代码了。
这样我们设计加入一个类负责为每个Point对象计数
Class UPoint{
private:
 friend class Handle;
 Point p;
 int u;
 Upoint():u(1){}
 Upoint(int x,int y):p(x,y),u(1){}
 Upoint(const Point& p0):p(p0),u(1){}
}

那么Handle类改成什么样呢:
Class Handle{
public:
 Handle();
 Handle(int,int);
 Handle(const Point&);
 Handle(const Handle& h):up(h.up){
  ++up->u;
 }
 Handle& operate=(const Handle& h){
  ++h.up->u;
  if(--up->u==0)
   delete up;
  up = h->up;
  return *this;
 }
 
 ~Handle(){
  if(--up->u == 0)
   delete up;
 }
 int x() const {return up->p.x();}
 Handle& x(int x0){
  up->p.x(x0);
  return *this;
 }
 int y() const {return up->p.y();}
 Handle& y(int y0){
  up->p.y(y0);
  return *this;
 }
private:
 //后来新加的
 Upoint * up;
}

这种是指针语义,永远不必复制UPoint对象,如果是需要值语义,则需要复制UPoint对象,保证UPoint不能同时被两个以上Handle所引用。
这可以通过看计数是否为1来判断。同时另外一种技术叫"Copy on write"写时复制。意思是对于不影响对象值的方法不去另外复制对象,
只有在会影响对象值的方法中去另外复制一个相同的对象:
Handle& Handle::x(int x0){
 if(up->u != 1){//如果有两个句柄指向同一个对象,则这里的计数已经大于1了,只是因为不去修改对象的值,一直没有复制出另外一个对象。
  --up->u;
  up = new UPoint(up->p);
 }
 up->p.x(x0);
 return *this;
}


这样的设计句柄有个缺点,就是需要定义一个具有类型为Point的成员的新类,这使得事情比较复杂,尤其是当要把Handle捆绑到Point的子类的时候。
怎样改进?这里有个方法,但并没有经常在使用的
class Handle{
public:
   //no change
private:
 Point* p; //去掉了UPoint
 int* u;
}
//新构造出来的Handle,初始计数=1就可以了
Handle::Handle():u(new int(1),p(new Point())){}
Handle::Handle(int x,int y):u(new int(1),p(new Point(x,y))){}
Handle::Handle(const Point& p0):u(new int(1),p(new Point(p0))){}
//复制构造函数,指针,计数的int地址都相同,计数加1
Handle::Handle(Handle& h):u(h.u),p(h.p){++*u;}

//赋值操作,就是原来this的计数要减1,新的指针计数加1.
Handle& Handle::operate=(const Hanlde& h){
 ++*h.u;
 if(--*u ==0){
  delete u;
  delete p;
 }
 u = h.u;
 p = h.p;
 return &this;
}

Handle::~Handle(){
 if(--*u ==0 ){
  delete u;
  delete p;
 }
}

再引申就是把int* u这个u定义出一个专门的类来。略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值