智能指针(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 阅读点滴记录(二)的更多相关文章

  1. C++primer 阅读点滴记录(三)

    14章 操作符重载和转换 重载操作符是具有特殊名称的函数:保留字operator后接需要定义的操作符符号. 1.重载的操作符名: + – * / % ^ & | ~ ! , = <  & ...

  2. C++primer 阅读点滴记录(一)

    第十三章 复制控制:(copy control) 复制构造函数(copy constructor) 复制操作符(assignment operator) ps: 什么时候需要显示的定义复制控制操作:类 ...

  3. Hadoop阅读笔记(二)——利用MapReduce求平均数和去重

    前言:圣诞节来了,我怎么能虚度光阴呢?!依稀记得,那一年,大家互赠贺卡,短短几行字,字字融化在心里:那一年,大家在水果市场,寻找那些最能代表自己心意的苹果香蕉梨,摸着冰冷的水果外皮,内心早已滚烫.这一 ...

  4. 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)

    本文是Tomcat源代码阅读系列的第二篇文章,我们在本系列的第一篇文章:在IntelliJ IDEA 和 Eclipse运行tomcat 7源代码一文中介绍了如何在intelliJ IDEA 和 Ec ...

  5. Material Calendar View 学习记录(二)

    Material Calendar View 学习记录(二) github link: material-calendarview; 在学习记录一中简单翻译了该开源项目的README.md文档.接下来 ...

  6. ZooKeeper源码阅读——client(二)

    原创技术文章,转载请注明:转自http://newliferen.github.io/ 如何连接ZooKeeper集群   要想了解ZooKeeper客户端实现原理,首先需要关注一下客户端的使用方式, ...

  7. Linux协议栈代码阅读笔记(二)网络接口的配置

    Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...

  8. Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客

    ==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...

  9. Apollo源码阅读笔记(二)

    Apollo源码阅读笔记(二) 前面 分析了apollo配置设置到Spring的environment的过程,此文继续PropertySourcesProcessor.postProcessBeanF ...

随机推荐

  1. NFS挂载启动

    NFS挂载启动参数: 1.服务器IP.目录(虚拟机IP和 NFS目录) 2.开发的IP 如下我的开发板设置 ipaddr=192.168.1.17           ① 开发板IP serverip ...

  2. python 赋值,交换值理解

    python里的赋值都是引用,第一次赋值就是定义. 看下面两个交换值的例子: 1. >>> a,b,c = 1,2,3 >>> a = b >>> ...

  3. 简单的python http接口自动化脚本

    今天给大家分享一个简单的Python脚本,使用python进行http的接口测试,脚本很简单,逻辑是:读取excel写好的测试用例,然后根据excel中的用例内容进行调用,判断预期结果中的返回值是否和 ...

  4. 深度解析国内O2O模式

    今日在网上发现这篇文章很棒,详细的分析了当前BAT矩阵下的o2o 的模式.所以转载过来与大家一起分享. 文章来自于:http://www.siilu.com/20151214/158917.shtml ...

  5. 【鸡渣饲料系列】《Introdution to 3D Game Programming With DirectX11》 代码转移至vs2015

    <Introdution to 3D Game Programming With DirectX11>我是从这本书学习的directx,被称为“龙书”dx11版,由于是通过这本书学习的所以 ...

  6. Social networks and health: Communicable but not infectious

    Harvard Men’s Health Watch Poet and pastor John Donne famously proclaimed “No man is an island.” It ...

  7. flash上传在spring mvc中出现的问题2

    转载请注明: TheViper http://www.cnblogs.com/TheViper  这两天本屌在做flash拼图上传遇到点坑 上传原理很简单,就是把上图右边画布区域BitmapData. ...

  8. 小巧的http live streaming m3u8播放器

    转载请注明: TheViper http://www.cnblogs.com/TheViper  原来发表过一篇分段播放的flash播放器.这个播放器其实就没有神马原理,就是把一个视频分成好几个视频, ...

  9. Android STL PORT

    ndk中包含了stl对应的库,在$(NKD_HOME)/sources/cxx-stl/stlport/stlport 有关Android NDK的C++ STL开发相关总结如下: 从Android ...

  10. ASP.NET MVC4 学习系统三(控制器Controller)

    控制器(Controllers)    在MVC架构模式的上下文里,控制器响应用户的输入(比如,用户点击“保存”按钮),并协调模型.视图以及(经常)数据访问层.在ASP.NET MVC程序里,控制器就 ...