STL中的智能指针auto_ptr可以实现简单的内存自动回收,防止内存泄漏(memory leakage)。auto_ptr实际是一个类,在该类析构时自动调用delete,从而达到了内存回收的效果。但是,由于同一个指针同一时刻只能被一个auto_ptr占用,如果采用赋值操作(=)或者拷贝构造函数调用,就会发生所有权转移,例如:

auto_ptr<int> p(new int(0));
auto_ptr<int> q;

此时,p拥有指向一个int的指针,q的指针为空。如果执行q=p;则,p指向空,q指向int;但是,这样所有权转换的问题同样发生在参数传递中,例如

void foo(auto_ptr<int> t);

如果调用 foo(p);那么p就丢失了指针,所以一个解决方法是用引用,例如:

void foo1(auto_ptr<int>& t);

void foo2 (const auto_ptr<int>& t);

两者都是可以的,不过foo1非常不安全,因为在函数里面很容易通过类似赋值的操作使t丢失指针,而foo2不会。例如

void foo2(const auto_ptr<int>& t)

     auto_ptr<int> m; m=t;
}

会发生编译错误,从而避免灾难的发生。但随之又出现一个很大的问题,就是auto_ptr类的拷贝构造函数,或者赋值函数。最理想的情况是这样(如果能成功,就不会有别的什么问题):

auto_ptr(const auto_ptr& rhs):ap(rhs.release()){}

但由于上述的原因,会发生编译错误(因为调用了release(),而release()会改变成员变量,不再是const)。所以只能去掉const,变为

auto_ptr(auto_ptr& rhs):ap(rhs.release()){}

这样可以编译成功,而且往往也能正确运行,但是唯一的问题是: 当rhs为右值时会出现问题。

为了简化问题,先假设拷贝构造函数什么都不做,即:

auto_ptr(auto_ptr& rhs){}

那么,如果有 auto_ptr<int> p(new int(10)),执行 auto_ptr<int> q(p),不会有任何问题,因为p是左值。但如果执行auto_ptr<int> q(auto_ptr<int>(new int(10))) ,则会发生编译错误,因为auto_ptr<int>(new int(10)) 是右值,对右值的引用只能是常引用,也就是"const auto_ptr& rhs"的形式。但这里要注意的是,刚才那段代码用VC编译没有任何问题,并且可以顺利运行,但是用GCC之类的标准c++就不能顺利编译。

在VC中auto_ptr<int>& p=auto_ptr<int>(new int(0))  是合法的,但在标准C++中是不合法的,只有const auto_ptr<int>& p=auto_ptr<int>(new int(0)) 才是合法的,也即在标准C++中,对右值的引用只能是常引用。所以说,要在标准C++中实现 auto_ptr<int> p(auto_ptr<int>(new int(0))) 就变得不可能了,因为如上所说,拷贝构造函数是这样的形式:auto_ptr(auto_ptr<T>& rhs):ap(rhs.release()){}

但是不能把右值传到一个非常引用中。但毕竟有聪明的人能想到解决办法,利用代理类( proxy class)声明如下结构,为了方便,我用int代替模板参

struct auto_ptr_ref
{
   int* p;
   auto_ptr_ref(int *t):p(t){}
};

然后在auto_ptr类中增加了以下函数

auto_ptr(auto_ptr_ref rhs):ap(rhs.p){}
auto_ptr& operator=(auto_ptr_ref rhs){reset(rhs.p); return *this;}
operator auto_ptr_ref(){return auto_ptr_ref(release());}

之后,如果在标准C++有以下调用(VC中也会按照这个步骤调用,虽然没有auto_ptr_ref它也能直接调用)

auto_ptr<int> p(auto_ptr<int>(new int(0)))

便可以成功,过程如下:

1. 构造临时对象 auto_ptr<int>(new int(0))

2. 想将临时对象通过拷贝构造函数传给p,却发现没有合适的拷贝构造函数,因为只有auto_ptr(auto_ptr& rhs)这个不能用,又没有auto_ptr(const auto_ptr& rhs) (因为用了在所有权转移中会出错)!

3. 编译器只能曲线救国,看看类型转换后能不能传递。

4. 由于我们定义了 operator auto_ptr_ref() 所以编译器自然就可以试一下转为 auto_ptr_ref类型。

5. 编译器猛然间发现,我们定义了 auto_ptr(auto_ptr_ref rhs):ap(rhs.p){} 的构造函数,可以传递。

6. 顺利构造p,任务完成。

其实说白了问题很简单,因为构造函数不能接受右值,则取中间左值=右值, 然后再让函数接受中间左值。 而这一系列过程正是利用编译器能够自动进行类型转换而完成的。

《C++标准程序库》读书笔记(三)相关推荐

  1. 黑客与画家 读书笔记

  2. mysql数据库权威指南_MySQL_MySQL权威指南读书笔记(三),第二章:MYSQL数据库里面的数 - phpStudy...

    MySQL权威指南读书笔记(三) 第二章:MYSQL数据库里面的数据 用想用好MYSQL,就必须透彻理解MYSQL是如何看待和处理数据的.本章主要讨论了两个问题:一是SQL所能处理的数据值的类型:二是 ...

  3. 《编程之美》读书笔记(三):烙饼问题与搜索树

    <编程之美>读书笔记三:烙饼问题与搜索树 薛笛 EMail:jxuedi#gmail.com 前面已经写了一些关于烙饼问题的简单分析,但因为那天太累有些意犹未尽,今天再充实一些内容那这个问 ...

  4. 《How Tomcat Works》读书笔记(三)--Connector(连接器)

    <How Tomcat Works>读书笔记(三)--Connector(连接器) 这是<How Tomcat Works>第三四章的读书笔记.主要写了Tomcat4.0默认的 ...

  5. TCPIP详解Protocol 读书笔记(三) IP协议讲解

    TCP/IP详解:Protocol 读书笔记(三) Chapter3 IP:网际协议 文章目录 TCP/IP详解:Protocol 读书笔记(三) Chapter3 IP:网际协议 IP协议 IP数据 ...

  6. 《大型网站技术架构》读书笔记三:大型网站核心架构要素

    来源:http://www.cnblogs.com/edisonchou/p/3806348.html 此篇已收录至<大型网站技术架构>读书笔记系列目录贴,点击访问该目录可获取更多内容. ...

  7. 《淘宝技术这十年》读书笔记 (三). 创造技术TFS和Tair

    前面两篇文章介绍了淘宝的发展历程和Java时代的变迁:             <淘宝技术这十年>读书笔记 (一).淘宝网技术简介及来源             <淘宝技术这十年&g ...

  8. Spring揭秘 读书笔记 三 bean的scope与FactoryBean

    本书可作为王富强所著<<Spring揭秘>>一书的读书笔记  第四章 BeanFactory的xml之旅 bean的scope scope有时被翻译为"作用域&quo ...

  9. 《你的灯亮着吗》 读书笔记三

    紧接<你的灯亮着吗>读书笔记二 4.这是谁的问题? 当别人可以妥善解决自己的问题时,不要越俎代庖,如果这是他们的麻烦,就让它成为他们的麻烦,如果一个人处于解决问题的位置,却并不受问题困扰, ...

  10. 需求工程:软件建模与分析 读书笔记三

    第四章 需求获取概述 读书笔记 在我们获取需求过程中会遇到很多困难,例如用户和开发人员的背景不同.立场不同,对统一信息的理解就会不同:普通用户缺乏概括性.综合性的表述能力:用户存在认知困境:用户越俎代 ...

最新文章

  1. Rabbitmq-理论基础
  2. NtQueryInformationProcess用法
  3. Kuebernetes之DaemonSet
  4. Spring之HibernateTemplate 和HibernateDaoSupport
  5. Transformer新内核Synthesizer:低复杂度的attention代替点乘式的注意力机制
  6. 黑龙江2021年高考成绩查询分数,2021年黑龙江高考成绩什么时候公布
  7. ES2021 更新的内容!
  8. linux中指令简约版
  9. 秀米图文排版转html,秀米微信编辑器图文排版H5秀图文教程
  10. GTQ服务多层次金融衍生品市场,促进社会经济繁荣
  11. rtorrent ubuntu端命令行种子下载器
  12. EXCEL中数字显示为E+18且尾数为0的解决方法
  13. 改oracle值,Oracle修改column值
  14. UG903中文文档分享(拒绝套路) | xilinx
  15. 机器学习模型管理平台_如何管理机器学习模型
  16. c语言 int 型 无符号数 %u
  17. 路缘石滑模机在公路建设中起到的那些作用
  18. 微信小程序兼容ios底部导航栏边距
  19. js对文件和二进制操作的一些方法汇总
  20. 目前服务器最大带宽是100M么?

热门文章

  1. C语言经典例86-两个字符串连接
  2. 【Android Gradle 插件】ProductFlavor 配置 ( AppExtension#externalNativeBuild 配置 | cmake 配置 | ndkBuild 配置 )
  3. 【Android 逆向】获取安装在手机中的应用的 APK 包 ( 进入 adb shell | 获取 root 权限 | 进入 /data/app/ 目录 | 拷贝 base.apk 到外置存储 )
  4. 【错误记录】Flutter 插件不兼容 ( requires Flutter SDK version >=1.22.0 <2.0.0, url_launcher >=5.7.7 <6.0.0- )
  5. 【Android RTMP】RTMP 直播推流阶段总结 ( 服务器端搭建 | Android 手机端编码推流 | 电脑端观看直播 | 服务器状态查看 )
  6. 【Java 网络编程】UDP 简介
  7. 【Android 应用开发】分析各种Android设备屏幕分辨率与适配 - 使用大量真实安卓设备采集真实数据统计
  8. 钉钉、阿里云和PaaS平台的整合开发
  9. PC问题-该虚拟机似乎正在使用中
  10. Linux 2.6 内核定时器