1、在【C++沉思录】代理类中,使用了代理类,存在问题:
a、代理复制,每次创建一个副本,这个开销有可能很大
b、有些对象不能轻易创建副本,比如文件
2、怎么解决这个问题?
使用引用计数句柄,对动态资源封装,句柄包含指针,多个句柄可以指向同一个对象。复制的时候,只是复制句柄的指针。
3、使用引用计数句柄,是为了避免不必要的对象复制,因此我们要知道有多少个句柄绑定到当前对象,也就是引用计数,
这样才能确定何时可以释放资源。
4、需要注意的是:引用计数不能是句柄的一部分,如果怎么做,当前句柄必须知道指向同一个对象的其他句柄,引用计数也要保持一致。
同时,引用计数不能成为对象的一部分,如果这样做,要求我们重写已经存在的对象类。
5、以Point类为例说明,解决办法是:增加一个新的类UPoint,包含Point对象和引用计数u,如下:
class Point
{
public:
Point():_x(0),_y(0){}
Point(int x,int y):_x(x),_y(y){}
Point(const Point& rhs):_x(rhs._x),_y(rhs._y){}

Point& SetX(int x)
{
_x = x;
return *this;
}

int GetX()
{
return _x;
}

Point& SetY(int y)
{
_y = y;
return *this;
}

int GetY()
{
return _y;
}

private:
int _x;
int _y;
};

#include "point.h"

// UPoint的目的是对Point和引用计数封装,用户是不可见的
class UPoint
{
friend class Handle_1;

private:
Point p;
int u;

UPoint():u(1){}

UPoint(int x,int y)
{
p.SetX(x);
p.SetY(y);
u = 1;
}

UPoint(const Point& rhs)
{
p = rhs;
u = 1;
}
};

6、现在考虑Handle_1的实现细节,
#include "u_point.h"

class Handle_1
{
public:
Handle_1():_up(new UPoint){}

Handle_1(int x,int y):_up(new UPoint(x,y)){}

Handle_1(const Point& rhs):_up(new UPoint(rhs)){}

~Handle_1()
{
subRef();
}

// copy构造,复制指针,增加引用
Handle_1(const Handle_1& rhs)
{
addRef(rhs._up);
}

// copy赋值,左边减少引用计数,判断是否delete,右边增加引用计数,考虑自我赋值
Handle_1& operator=(const Handle_1& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs._up);
}

return * this;
}

int GetX()
{
return _up->p.GetX();
}

int GetY()
{
return _up->p.GetY();
}

Handle_1& SetX(int x)
{
_up->p.SetX(x);
return *this;
}

Handle_1& SetY(int y)
{
_up->p.SetY(y);
return *this;
}

private:
void addRef(UPoint* up) // 复制指针,增加引用
{
_up = up;
++_up->u;
}

void subRef() // 减少引用,判断是否delete
{
if(--_up->u == 0)
{
delete _up;
}
}

private:
UPoint* _up;
};

7、考虑下面的情况,
Handle_1 h1(3,4);
Handle_1 h2(h1);
h2.SetX(5);
int dd = h1.GetX();
dd的值是5,也就是说,多个句柄指向同一个对象,避免了不必要的对象复制,实现的是 指针语义。但是对于上面的情况,往往不是用户所期望的,
怎么解决这个问题?
8、使用写时拷贝,每次修改的时候重新创建一个对象。也就是说,修改的时候变成值语义,原对象h1是不可变对象,使用h2修改,会导致重新创建一个对象。
如下:
Handle_1& SetX(int x)
{
//_up->p.SetX(x);
if(_up->u == 1) // 当前是唯一的引用
{
_up->p.SetX(x);
}
else
{
--_up->u;
_up = new UPoint(x,_up->p.GetY());
}
return *this;
}

Handle_1& SetY(int y)
{
//_up->p.SetY(y);
if(_up->u == 1) // 当前是唯一的引用
{
_up->p.SetY(y);
}
else
{
--_up->u;
_up = new UPoint(_up->p.GetX(),y);
}
return *this;
}

【C++沉思录】句柄1的更多相关文章

  1. 【C++沉思录】句柄2

    1.[C++沉思录]句柄1 存在问题: 句柄为了绑定到Point的对象上,必须定义一个辅助类UPoint,如果要求句柄绑定到Point的子类上,那就存在问题了.2.有没有更简单的办法呢? 句柄使用Po ...

  2. 生活沉思录 via 哲理小故事(四)

    1.围墙里的墓碑 第一次世界大战期间,驻守意大利某小镇的年轻军官结识了镇上的牧师.虽然军官信仰信教,而牧师是天主教牧师,但两人一见如故. 军官在一次执行任务中身负重伤,弥留之际嘱托牧师无论如何要把自己 ...

  3. 生活沉思录 via 哲理小故事

    本文转载:http://www.cnblogs.com/willick/p/3174803.html 1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛, ...

  4. 生活沉思录 via 哲理小故事(一)

    1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...

  5. Atitit。 沉思录 与it软件开发管理中的总结 读后感

    Atitit. 沉思录 与it软件开发管理中的总结 读后感 1. <沉思录>,古罗马唯一一位哲学家皇帝马可·奥勒留所著 2 2. 沉思录与it软件开发管理中的总结 2 2.1. 要有自己的 ...

  6. c++沉思录 学习笔记 第六章 句柄(引用计数指针雏形?)

    一个简单的point坐标类 class Point {public: Point():xval(0),yval(0){} Point(int x,int y):xval(x),yval(y){} in ...

  7. c++学习书籍推荐《C++沉思录》下载

    百度云及其他网盘下载地址:点我 编辑推荐 经典C++图书,应广大读者的强烈要求再版 目录 第0章 序幕第一篇 动机第1章 为什么我用C++第2章 为什么用C++工作第3章 生活在现实世界中 第二篇 类 ...

  8. C++模板沉思录(上)

    花下猫语: 在我们读者群里,最近出现了比较多关于 C++ 的讨论,还兴起了一股学习 C++ 的风气.樱雨楼小姐姐对 C++ 的模板深有研究,系统地梳理成了一篇近 4 万字的文章!本文是上篇,分享给大家 ...

  9. C++模板沉思录

    0 论抽象--前言 故事要从一个看起来非常简单的功能开始: 请计算两个数的和. 如果你对Python很熟悉,你一定会觉得:"哇!这太简单了!",然后写出以下代码: def Plus ...

随机推荐

  1. (Unity)Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进展混淆,避免被反编译

    Unity自定义Debug日志文件,利用VS生成Dll文件并使用Dotfuscated进行混淆,避免被反编译. 1.打开VS,博主所用版本是Visual Studio 2013. 2.新建一个VC项目 ...

  2. 在centos上编译安装mariadb数据库

    一.安装前提(准备数据文件.安装其他依赖的软件) 1.准备数据存放的目录 [root@localhost ~]# fdisk /dev/sdb  (fdisk /dev/sdb 创建一个逻辑分区/de ...

  3. jQuery学习总结(二)

    简单选择器: 在使用jQuery 选择器时,我们首先必须使用“$()”函数来包装我们的CSS 规则. 而CSS 规则作为参数传递到jQuery 对象内部后,再返回包含页面中对应元素的jQuery 对象 ...

  4. 4.13-4.17c语言学习

    这周学习开始接触c语言,使用的工具是c-free5,主要是把之前的一些函数流程图通过编写代码实现运行,本周最后一天的作业是做简易的atm机运行逻辑程序,是在main主函数外附加使用void函数,其主要 ...

  5. BZOJ3329 Xorequ(数位DP)

    题目大意:x xor 2x=3x(与x xor 3x=2x等价)求满足等式且小于n的x的个数,与满足等式小于2n的数的个数. 因为异或是不进位的二进制加法,那么因为结果正好和加法相同,那么说明x在二进 ...

  6. NBIbatis 框架体系说明

    框架体系说明 Application 表现层 表现层必须通过Business业务规则层操作数据库,不能直接调用DataAccess数据访问. Sqlmap.config配置: connectionSt ...

  7. Python变量/运算符/函数/模块/string

    Python笔记(一) 1.变量类型 Python 有五个内置的简单类型:bool.int.long.float 和 complex.这些类型是不可变的,就是说整数对象一旦创建,其类型便不可更改. t ...

  8. [芯片] 4、接口技术·实验四·串行接口8251A

    目录 一.实验目的和要求... 2 二.实验原理与背景... 3 三.实验具体的内容... 3 四.实验的代码说明... 4 五.实验结果的分析... 6 附录资料 一.实验目的和要求 学会8251芯 ...

  9. AspNet MVC 缓存

    服务端缓存技术 请求域内的缓存 每个Asp.Net请求都会在Asp.Net框架中创建一个新的System.Web.HttpContext对象(HttpContext对象封装有关个别 HTTP 请求的所 ...

  10. .NET读取Office文件内容(word、excel、ppt)

    引用命名空间 using Microsoft.Office.Core; using Word = Microsoft.Office.Interop.Word; using Excel = Micros ...