《C++沉思录》通过句柄来避免不必要的对象的复制

原创 2006年06月14日 10:22:00

        在上一篇文章中,多次对象的复制工作,浪费了内存空间,同时也影响了程序的效率。在这里我们采用句柄的方法,消除不必要的复制。通过一个句柄来引用对象和一个引用计数器来控制该对象的创建与消除,这里所说的句柄是一个句柄类(Handle),其实就是一个指向对象的指针,当我们引用一次该对象的时候就将引用计数器加一,当计数器为零的时候,表示没有任何地方使用该对象,此时我们就要消除该对象,同时释放该对象所占用的空间。书中讲解的程序片断,整理如下:

class point     //一个point类
{
public:
 point(int x = 0, int y = 0) : xval(x), yval(y) { }
 int x(void) const { return xval; }
 int y(void) const { return yval; }
 point &x(int xv) { xval = xv; return *this; }
 point &y(int yv) { yval = yv; return *this; }
private:
 int xval, yval;
};


class UPoint    //通过一个类来控制对象,以及它的计数器
{
 friend class Handle;    //将handle设置为该对象的友元,这样就可以使用该类的私有成员
 point p;
 int u;
 UPoint(void) : u(1) { }
 UPoint(int x, int y) : p(x, y), u(1) { }
 UPoint(const point& p0) : p(p0), u(1) { }
};
class Handle
{
public:
 Handle(void) : up(new UPoint) { }
 Handle(int x,int y) : up(new UPoint(x, y)) { }
 Handle(const point& p) : up(new UPoint(p)) {}
 Handle(const Handle* h) :up(h->up) { ++up->u; }
 Handle& operator=(const Handle& h)
 {
  ++h.up->u;
  if (--up->u == 0)
  {
   delete up;
  }
  up = h.up;
  return *this;
 }
 ~Handle(void)
 {
  if (--up->u == 0)
  {
   delete up;
  }
 }

 int x(void) const { return up->p.x(); }
 Handle& x(int x0)
 {
  if (up->u != 1)   //在句柄的复制过程中,不希望在修改原对象的值,所以就要new一个新的对象出来,对新对象进行操作,在这个地方,不知为什么不直接在handle的拷贝构造中new新的对象而要在这里new新的对象???
  {
   --up->u;
   up = new UPoint(up->p);
  }
  up->p.x(x0);
  return *this;
 }
 int y(void) const { return up->p.y(); };
 Handle& y(int y0)
 {
  if (up->u != 1)
  {
   --up->u;
   up = new UPoint(up->p);
  }
  up->p.y(y0);
  return *this;
 }
private:
 UPoint *up;
};

      在上面的程序中,的确避免的不必要的对象复制,只需要一个句柄我们就可以高效的使用这个对象。同时,在这段代码中还有一个问题:我们都要借助一个类(UPoint)来使用这个对象,将句柄邦定到该对象上,但是如果这个对象是未知的话,也就是说根本就不知道要将这个句柄邦定到那个对象上,这是我们也就无从定义UPoint。针对这一问题提出了新的解决方法,其主要思想是:将引用计数从数据中分离出来,把引用计数加到handle中去,也就不用往对象上邦定任何东西。

《C语言及程序设计进阶》网络课程主页

在CSDN学院开出的网络系列课程《C语言及程序设计初步》已经完成。系列中的第二季《C语言及程序设计提高》的所有资源建设已经全部完成。这是第三季《C语言及程序设计进阶》,争取在6月底前完成。知识点视频示...

《C++ 沉思录》阅读笔记——句柄类

在上一篇博文里,我介绍了代理类的相关内容,如果记性好的朋友,应该已经对代理类有了比较深入的认识。在设计代理类的过程中,我们遇到的核心问题是:内存的分配和编译时类型未知对象的绑定。我们通过让所有子类自定...

《C++沉思录》 第六章 句柄 第一部分

      简单回顾一下第五章节,Andrew Koening向我们提出了一个问题,在一个继承体系中,如何设计一个容器可以容纳各个不同的子类对象。显然无法使用基类对象数组,如果是抽象基类,没有办法进行...

C++沉思录读书笔记(7章)-句柄:第二部分

上一回讨论的句柄技术有一个明显的缺点:为了将句柄捆绑到类T的对象上,必须要新定义一个具有类型为T的成员对象的新类。 这个毛病相当麻烦,如果想新设计一个类的句柄类,就需要新定义两个类。 ...

C++沉思录读书笔记(7章)-句柄:第二部分

原文:http://blog.csdn.net/yucan1001/article/details/6919704 上一回讨论的句柄技术有一个明显的缺点:为了将句柄捆绑到类T的对象上,必须要...

《C++沉思录》-第七章-句柄:第二部分

第六章谈及一种向类中添加句柄和引用计数的技术,以能够通过值控制引用计数就能够高效地“复制”该类的对象。这种技术有一个明显的缺点:为了把句柄绑定到类T的对象上,必须定义一个具有类型T的成员的新类。 ...

《C++沉思录》——类设计核查表、代理类、句柄类

《C++沉思录》——类设计核查表、代理类、句柄类

C++沉思录-第6章 句柄

语义句柄首先列出测试文件:#include "stdafx.h" #include #include "Point.h" using namespace std;int main() { H...

句柄-摘自《C++沉思录》Andrew Koenig

代理类能让我们在一个容器中
  • locklzg
  • locklzg
  • 2014年06月07日 15:53
  • 631

C++沉思录-第7章 句柄二 引用计数的分离

第六章的句柄,通过UPoint类封Point实现句柄的绑定。 UPoint类的使用只是为了实现引用计数,因此,本章的任务是不再实现额外的UPoint,只将引用计数进行单独考量。 简单的引用计数...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:《C++沉思录》通过句柄来避免不必要的对象的复制
举报原因:
原因补充:

(最多只允许输入30个字)