【C++沉思录】句柄2
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的更多相关文章
- 【C++沉思录】句柄1
1.在[C++沉思录]代理类中,使用了代理类,存在问题: a.代理复制,每次创建一个副本,这个开销有可能很大 b.有些对象不能轻易创建副本,比如文件2.怎么解决这个问题? 使用引用计数句柄,对动态资源 ...
- 生活沉思录 via 哲理小故事(四)
1.围墙里的墓碑 第一次世界大战期间,驻守意大利某小镇的年轻军官结识了镇上的牧师.虽然军官信仰信教,而牧师是天主教牧师,但两人一见如故. 军官在一次执行任务中身负重伤,弥留之际嘱托牧师无论如何要把自己 ...
- 生活沉思录 via 哲理小故事
本文转载:http://www.cnblogs.com/willick/p/3174803.html 1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛, ...
- 生活沉思录 via 哲理小故事(一)
1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...
- Atitit。 沉思录 与it软件开发管理中的总结 读后感
Atitit. 沉思录 与it软件开发管理中的总结 读后感 1. <沉思录>,古罗马唯一一位哲学家皇帝马可·奥勒留所著 2 2. 沉思录与it软件开发管理中的总结 2 2.1. 要有自己的 ...
- c++沉思录 学习笔记 第六章 句柄(引用计数指针雏形?)
一个简单的point坐标类 class Point {public: Point():xval(0),yval(0){} Point(int x,int y):xval(x),yval(y){} in ...
- c++学习书籍推荐《C++沉思录》下载
百度云及其他网盘下载地址:点我 编辑推荐 经典C++图书,应广大读者的强烈要求再版 目录 第0章 序幕第一篇 动机第1章 为什么我用C++第2章 为什么用C++工作第3章 生活在现实世界中 第二篇 类 ...
- C++模板沉思录(上)
花下猫语: 在我们读者群里,最近出现了比较多关于 C++ 的讨论,还兴起了一股学习 C++ 的风气.樱雨楼小姐姐对 C++ 的模板深有研究,系统地梳理成了一篇近 4 万字的文章!本文是上篇,分享给大家 ...
- C++模板沉思录
0 论抽象--前言 故事要从一个看起来非常简单的功能开始: 请计算两个数的和. 如果你对Python很熟悉,你一定会觉得:"哇!这太简单了!",然后写出以下代码: def Plus ...
随机推荐
- Java集合的运算之减法A-B
import com.sun.media.sound.SoftSynthesizer; import java.util.*; public class a123 { public static ...
- Win7(32/64)VS2010配置编译GDAL环境(图文教程+亲测可用!)
最近的一个VS2010的项目中用到了GDAL,关于GDAL这个库的说明与赞美,这里就不赘述了,下面是在VS2010中配置GDAL的详细过程. 系统说明 Win7(32位/64位),VS2010,GDA ...
- Android性能优化方法(四)
在一个应用程序中,一般都会存在多个Activity,每个Activity对应着一个UI布局文件.一般来说,为了保持不同窗口之间的风格统一,在这些UI布局文件中,几乎肯定会用到很多相同的布局.如果我们在 ...
- Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)
前言 很久没更新博客了,加上刚过年,现在准备重新开战,继续自己的学习之路.本文已同步到Web API2系列文章中http://www.cnblogs.com/aehyok/p/3446289.html ...
- node-webkit教程(14)禁用缓存
1.在开发者工具中禁用缓存 上面这张图,是在node-webkit 中 在开发工具中配置禁用缓存的选项. 使用这个选项可以有效的禁用所有页面缓存. 2. 在配置文件中,配置webkit 缓存禁用和启用 ...
- 深入理解java虚拟机【垃圾回收算法】
Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...
- 团队项目 SRS文档
一:实验内容:用例模型的建立 简介: 图书管理系统是使用计算机实现图书大量信息处理的电子档案管理系统,在本系统中主要满足借书者.图书管理员和系统管理员3方面的需求.对借书者来说主要是查询个人信息.查询 ...
- [JS4] 最简单JS框架
<html> <head> <title></title> <SCRIPT TYPE="text/JavaScript"> ...
- 说不尽的MVVM(2) – MVVM初体验
知识预备 阅读本文,我假定你已经具备以下知识: C#.WPF基础知识 了解Lambda表达式和TPL 对事件驱动模型的了解 知道ICommand接口 发生了什么 某程序员接到一个需求,编写一个媒体渲染 ...
- js操作textarea方法集合
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...