C++primer 阅读点滴记录(二)
智能指针(smart point)
除了增加功能外,其行为像普通指针一样。 一般通过使用计数(use count)或引用计数(reference count)实现智能指针,防止出现指针垂悬。
下面是一个普通带指针的类代码:
#ifndef HASPTR_H
#define HASPTR_H class HasPtr{
public:
HasPtr(int *p, int i):ptr(p),val(i){}
int *get_ptr()const{return ptr;}
int get_int()const{return val;} void set_ptr(int *p){ptr = p;}
void set_int(int i){val = i;} int get_ptr_val()const{return *ptr;}
void set_ptr_val(int val)const{ *ptr = val;}
private:
int *ptr; //common pointer
int val;
}; #endif // HASPTR_H
小心地雷:
具有指针成员且使用默认合成构造函数的类具有普通指针的所有缺陷。尤其是,类本身无法避免垂悬指针。
一般有两种策略使用引用计数:
1、单独定义一个具体类用以封装使用计数和相关指针:(一般将该类设为私有类,仅友元类可以访问)
//private class for use by HasPtr only
class U_ptr{
friend class HasPtr;
int *ip;
size_t use;
U_ptr(int* p):ip(p),use(1){}
~U_ptr(){delete ip;}
}; HasPtr& HasPtr::operator =(const HasPtr& rhs){
++rhs.ptr->use;//increment use count on rhs first
if(--ptr->use == 0) //if use count goes to 0 on this object, delete it
delete ptr;
ptr = rhs.ptr;//copy the U_ptr
val = rhs.val;//copy the int member
return *this;
}
下面是原来的HasPtr类
class HasPtr{
public:
//HasPtr owns the pointer, p must been dynamically allocalted
HasPtr(int *p, int i):ptr(new U_ptr(p)),val(i){}
//copy memebers and increment the use count
HasPtr(const HasPtr& orig):
ptr(orig.ptr),val(orig.val){ ++ptr->use;}
HasPtr& operator=(const HasPtr&);
//if use count goes zero, delete th U_ptr object
~HasPtr(){
if (--ptr->use == 0)
delete ptr;
}
int *get_ptr()const{return ptr->ip;}
int get_int()const{return val;}
void set_ptr(int *p){ptr->ip = p;}
void set_int(int i){val = i;}
int get_ptr_val()const{return *ptr->ip;}
void set_ptr_val(int val){*ptr->ip = i;}
private:
U_ptr* ptr;
int val;
};
复制操作比复制构造函数要复杂点,一般现将右操作数引用计数加1, 然后左操作数对象引用计数减1并检查这个引用计数。
HasPtr& HasPtr::operator =(const HasPtr& rhs){
++rhs.ptr->use;//increment use count on rhs first
if(--ptr->use == 0) //if use count goes to 0 on this object, delete it
delete ptr;
ptr = rhs.ptr;//copy the U_ptr
val = rhs.val;//copy the int member
return *this;
}
注解: 这个赋值操作符在减少左操作数的使用计数之前使rhs的使用计数加1,从而防止自身赋值。
现在需要改变访问int*的其他成员,以便通过U_ptr指针简洁获取int
定义值类型:
处理指针成员的另一种完全不同的方法,是给指针成员提供值语义(value semantics), 复制值对象时,会得到一个不同的新副本。对副本的操作不会反映到原有对象上,反之亦然。
代码示例如下:
#ifndef VALUE_PTR_H
#define VALUE_PTR_H class HasPtr{
public:
HasPtr(const int&p, int i):ptr(new int(p)),val(i){}
HasPtr(const HasPtr& orig):ptr(new int(*orig.ptr)),val(orig.val){}
HasPtr& operator=(const HasPtr&);
~HasPtr(){delete ptr;} int get_ptr_val()const{return *ptr;}
int get_int()const{return val;} void set_ptr(int* p){ptr = p;}
void set_int(int i){val = i;} int* get_ptr()const{return ptr;}
void set_ptr_val(int val){*ptr = val;}
private:
int* ptr;
int val;
}; HasPtr& HasPtr::operator =(const HasPtr& rhs){
*ptr = *rhs.ptr; //copy the value pointer to
val = rhs.val; //copy the int
return *this;
}
#endif // !VALUE_PTR_H
注解: 即使要讲一个对象赋值给它本身,赋值操作符也必须总是保证正确。 本例中,即使左右操作数相同,操作本质上也是安全的,因此,不需要显示检查自身赋值。
C++primer 阅读点滴记录(二)的更多相关文章
- C++primer 阅读点滴记录(三)
14章 操作符重载和转换 重载操作符是具有特殊名称的函数:保留字operator后接需要定义的操作符符号. 1.重载的操作符名: + – * / % ^ & | ~ ! , = < & ...
- C++primer 阅读点滴记录(一)
第十三章 复制控制:(copy control) 复制构造函数(copy constructor) 复制操作符(assignment operator) ps: 什么时候需要显示的定义复制控制操作:类 ...
- Hadoop阅读笔记(二)——利用MapReduce求平均数和去重
前言:圣诞节来了,我怎么能虚度光阴呢?!依稀记得,那一年,大家互赠贺卡,短短几行字,字字融化在心里:那一年,大家在水果市场,寻找那些最能代表自己心意的苹果香蕉梨,摸着冰冷的水果外皮,内心早已滚烫.这一 ...
- 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)
本文是Tomcat源代码阅读系列的第二篇文章,我们在本系列的第一篇文章:在IntelliJ IDEA 和 Eclipse运行tomcat 7源代码一文中介绍了如何在intelliJ IDEA 和 Ec ...
- Material Calendar View 学习记录(二)
Material Calendar View 学习记录(二) github link: material-calendarview; 在学习记录一中简单翻译了该开源项目的README.md文档.接下来 ...
- ZooKeeper源码阅读——client(二)
原创技术文章,转载请注明:转自http://newliferen.github.io/ 如何连接ZooKeeper集群 要想了解ZooKeeper客户端实现原理,首先需要关注一下客户端的使用方式, ...
- Linux协议栈代码阅读笔记(二)网络接口的配置
Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...
- Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客
==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...
- Apollo源码阅读笔记(二)
Apollo源码阅读笔记(二) 前面 分析了apollo配置设置到Spring的environment的过程,此文继续PropertySourcesProcessor.postProcessBeanF ...
随机推荐
- LaTex学习笔记
常见符号大全:http://ia.wikipedia.org/wiki/Wikipedia:LaTeX_symbols 字体加粗: \textbf{} 换页:\newpage 大于等于,小于等于 ...
- bitmap size exceeds VM budget
bitmap size exceeds VM budget we can avoid this error by the following parts:1 its not how much ima ...
- 05-UIKit绘图演练
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- NoSuchMethodError: resolveTypeArguments
NoSuchMethodError: resolveTypeArguments——因为spring版本冲突导致,观察解压war包后lib中有几个spring.在pom中通过exclusion解决 Ht ...
- Codeforces Round #219 (Div. 1) C. Watching Fireworks is Fun
C. Watching Fireworks is Fun time limit per test 4 seconds memory limit per test 256 megabytes input ...
- CS中调用微软自带com组件实现音频视频播放(wf/wpf)
1.mp3播放器:工具箱中右键,在弹出的菜单中选择“选择项”,添加“com组件”,选择名称“windows Media Player",点击确定就会在工具箱新增一个“windows Medi ...
- 下拉列表autocomplete各种实现方式比较
方法一:用form 表单的datalist属性,此时会以首字母补充排序.实现效果参考:http://www.w3schools.com/html/tryit.asp?filename=tryhtml_ ...
- NOIP1998 拼数
http://www.luogu.org/problem/show?pid=1012 题目描述 设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数. 例如:n=3时,3个整数13,3 ...
- 转)SSO单点登录在互联网电商应用中的解决方案(基于CAS的改造)
电商平台中无论是前端还是后端会存在大量的业务应用,在整个交易的过程中请求是在各个业务应用中流转的,对于用户来讲只需要登录一次就可以访问所有的业务,这就是单点登录SSO. 单点登录开源有很多的解决方案, ...
- 【HTML/XML 12】URI、URN、URL的联系和区别
导读:在学习XML的时候,书中有很多个地方都提到URL等几个概念,再之前做项目的时候,重定向或是转发时,也用到了这个URL,在学习Ajax时,ajax破坏了统一资源定位(URN)都或多或少的接触到了这 ...