句柄类(handle class)(一)

句柄类(handle class)(一)问题:对于某些类来说,能够避免复制其对象是很有好处的。因为有可能对象太大,复制起来消耗太大。也有可能每个对象代表一种不能被轻易复制的资源,譬如文件等等情况。需要有一种方法,让我们在避免某些缺点(缺乏安全性)的同时能够获取指针的某些优点。尤其是在保持多态性的前提下,避免复制对象的代价,因此我们引入句柄类来解决这一问题。以一个简单的类作为例子。关于这个类有必要做三点说明1.如果使用Point(int…

大家好,欢迎来到IT知识分享网。

问题:对于某些类来说,能够避免复制其对象是很有好处的。因为有可能对象太大,复制起来消耗太大。也有可能每个对象代表一种不能被轻易复制的资源,譬如文件等等情况。需要有一种方法,让我们在避免某些缺点(缺乏安全性)的同时能够获取指针的某些优点。尤其是在保持多态性的前提下,避免复制对象的代价,因此我们引入句柄类来解决这一问题。

以一个简单的类作为例子。

句柄类(handle class)(一)

关于这个类有必要做三点说明

1.如果使用 Point(int x = 0, int y = 0): xval(x), yval(y) {}

来代替上述的两个构造函数,毫无疑问,可以只需给出x的值便可以构造一个Point对象。而这样做几乎可以肯定是错的。因为一个点不可能只通过x的值就能确定。

2.重载了x和y成员函数

3.之所以将修改类的对象的成员函数的返回值设置为Point&,是因为这样做便可以连续调用该函数以修改对象。如果P是Point的一个对象,那么便可以使用P.x(2).y(2)的形式修改对象。

接下来我们要考虑的是如何将Point对象绑定到句柄。

之所以使用句柄,原因之一是为了避免不必要的对象复制。也就是说得允许多个句柄绑定到单个对象上。将handle类直接绑定到对象P上,那么handle最好与P的内存分配和释放无关。考虑这样的情况,Handle h(P);如果这样直接绑定,一旦P被删除,Handle会怎样呢?显然,删除P之后应该使Handle无效,那么Handle如何知道P被删除了呢?或者说,应该同时删除Handle吗?如果P是一个局部变量,那么P就会被删除两次,Handle离开时一次,P超出自己作用域一次。

因此,handle应该“控制”它所绑定的到的对象,也就是说handle应该创建和销毁对象。有两种可能的选择:

1.Handle h0(123, 456)即把用于创建Point的参数传给这个handle。

2.Handle h(p) 即创建自己的Point对象并把它赋给一个handle去进行复制。

简单的实现:

句柄类(handle class)(一)

引用计数型句柄

我们必须了解有多少个句柄绑定在同一对象上,只有这样才能确定应当在何时删除对象。借鉴智能指针tr1::shared_ptr的工作机制,我们使用引用计数来达到这个目的。当然这个引用计数不能是句柄的一部分。我们必须重新定义一个类来容纳一个引用计数和一个Point对象。这个类纯粹是为了实现而设计的。

句柄类(handle class)(一)

到这我们可以回到Handle类,来完成成员函数的设计。

句柄类(handle class)(一)

接下来我们再考虑最后一个问题,我们的句柄是需要值语义还是指针语义。看下面的例子

Handle h(3,4);

Handle h2 = h;

h2.x(5);

int n = h.x();

如果希望句柄为值语义,则在这个例子中,我们希望n等于3。即绑定到同一对象的句柄互不影响。如果采用指针语义则是相反的情况。因此有以下两种实现方式。

指针语义:

句柄类(handle class)(一)

值语义:

句柄类(handle class)(一)

需要注意的是,原来Handle的引用计数可能不为1,所以需要保证新的Handle引用计数为1。这就意味着我们需要在UPoint这个类中添加一个私有成员函数,来设置引用计数。

上面的代码运用了一种叫做写时复制(copy on write),其优点是只有在绝对必要时才进行复制,从而避免了不必要的复制,而且额外开销也只有一点点。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/10747.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信