1、【C++沉思录】句柄1 存在问题:
句柄为了绑定到Point的对象上,必须定义一个辅助类UPoint,如果要求句柄绑定到Point的子类上,那就存在问题了。
2、有没有更简单的办法呢?
句柄使用Point*直接绑定到Point对象上(包括子类),为了保持多个句柄引用计数的一致性,使用int* 指向引用计数。
3、代码如下:
#include "point.h"
class Handle_2
{
public:
Handle_2():_p(new Point),_u(new int(1)){}

Handle_2(int x,int y):_p(new Point(x,y)),_u(new int(1)){}

Handle_2(const Point& rhs):_p(new Point(rhs)),_u(new int(1)){}

~Handle_2()
{
subRef();
}

Handle_2(const Handle_2& rhs)
{
addRef(rhs);
}

Handle_2& operator=(const Handle_2& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs);
}

return * this;
}

int GetX()
{
return _p->GetX();
}

int GetY()
{
return _p->GetY();
}

Handle_2& SetX(int x)
{
if(*_u == 1) // 当前是唯一的引用
{
_p->SetX(x);
}
else
{
--*_u;
_p = new Point(x,_p->GetY());
}
return *this;
}

Handle_2& SetY(int y)
{
if(*_u == 1) // 当前是唯一的引用
{
_p->SetY(y);
}
else
{
--*_u;
_p = new Point(_p->GetX(),y);
}
return *this;
}

private:
void addRef(const Handle_2& rhs) // 复制对象指针和引用计数指针,增加引用
{
_p = rhs._p;
_u = rhs._u;
++*_u;
}

void subRef()// 减少引用,判断是否delete对象和引用计数
{
if(--*_u == 0)
{
delete _p;
delete _u;
}
}

private:
Point* _p;
int* _u;
};
4、这里要手动管理动态内存 int* _u; 同样道理,可以使用栈上对象进行管理,抽象出一个辅助类 UseCount
class UseCount
{
public:
UseCount():_p(new int(1)){}
UseCount(const UseCount& rhs)
{
addRef(rhs);
}

UseCount& operator=(const UseCount& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs);
}
return *this;
}

~UseCount()
{
subRef();
}

bool IsOnly()
{
return (*_p == 1);
}

void MakeOnly()
{
if(IsOnly()) // 防止已经是only,用户还调用MakeOnly
{
return;
}
--*_p;
_p = new int(1);
}

private:
void addRef(const UseCount& rhs)
{
_p = rhs._p;
++*_p;
}

void subRef()
{
if(--*_p == 0)
{
delete _p;
}
}

private:
int* _p;
};

#include "point.h"
#include "use_count.h"
class Handle_2
{
public:
Handle_2():_p(new Point){}

Handle_2(int x,int y):_p(new Point(x,y)){}

Handle_2(const Point& rhs):_p(new Point(rhs)){}

~Handle_2()
{
subRef();
}

Handle_2(const Handle_2& rhs)
{
addRef(rhs);
}

Handle_2& operator=(const Handle_2& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs);
}

return * this;
}

int GetX()
{
return _p->GetX();
}

int GetY()
{
return _p->GetY();
}

Handle_2& SetX(int x)
{
if(_u.IsOnly()) // 当前是唯一的引用
{
_p->SetX(x);
}
else
{
_u.MakeOnly();
_p = new Point(x,_p->GetY());
}
return *this;
}

Handle_2& SetY(int y)
{
if(_u.IsOnly()) // 当前是唯一的引用
{
_p->SetY(y);
}
else
{
_u.MakeOnly();
_p = new Point(_p->GetX(),y);
}
return *this;
}

private:
void addRef(const Handle_2& rhs)
{
_p = rhs._p;
_u = rhs._u;
}

void subRef()
{
if(_u.IsOnly())
{
delete _p;
}
}

private:
Point* _p;
UseCount _u;
};

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

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

    1.在[C++沉思录]代理类中,使用了代理类,存在问题: a.代理复制,每次创建一个副本,这个开销有可能很大 b.有些对象不能轻易创建副本,比如文件2.怎么解决这个问题? 使用引用计数句柄,对动态资源 ...

  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. Linux 修改IP地址

    vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE="eth0" BOOTPROTO="static" #静 ...

  2. 5.7 NDK开发

    JNI开发流程主要分为以下6步: 编写Java源代码 将Java源代码编译成class字节码文件 用javah -jni命令生成.h头文件(-jni参数表示将class中用native声明的函数生成j ...

  3. 第35讲:List的map、flatMap、foreach、filter操作代码实战

    List类的高阶方法          val fmap = List( 1,2 ,3). map { _ + 1 } //List(2, 3, 4)    val fruit_rev2 = frui ...

  4. spring-data-elasticsearch整合elasticsearch

    花了一个晚上 整合最新版本的spring-data-elasticsearch与elasticsearch,遇到各种版本冲突 之类的问题,测试效果如图: facet搜索:

  5. Oracle数据库字符集修改

    Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系.ORACLE支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据.一般来说,数据库字符集在安装数据库实例时就 ...

  6. [转]一个文件上传的jquery插件

    http://www.jb51.net/article/51547.htm 这篇文章主要介绍了使用ajaxfileupload.js实现ajax上传文件php版,需要的朋友可以参考下     无论是P ...

  7. [ACM_水题] 不要62(hdu oj 2089, 不含62和4的数字统计)

    Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer).杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来, ...

  8. [ucgui] 对话框3——GUIBuilder生成界面c文件及修改

    >_<" 其实生成GUI有相应的工具:

  9. Linux: shell常用通配符

    字符 含义 * 匹配 0 或多个字符 ? 匹配任意一个字符 [list] 匹配 list 中的任意单一字符 [!list] 匹配 除list 中的任意单一字符以外的字符 [c1-c2] 匹配 c1-c ...

  10. 带你看懂Dictionary的内部实现

    了解Dictionary的开发人员都了解,和List相比,字典添加会慢,但是查找会比较快,那么Dictionary是如何实现的呢? Dictionary的构造 下面的代码我看看Dictionary在构 ...