当前位置: 首页 > news >正文

《C++编程风格(修订版)》——2.6 动态内存的回收

本节书摘来自异步社区出版社《C++编程风格(修订版)》一书中的第2章,第2.6节,作者:【美】Tom Cargill,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.6 动态内存的回收

C++编程风格(修订版)
string 类在管理动态内存时还存在着第二个问题:“内存泄漏”,当所有使用 new 来分配的动 态内存并没有都使用 delete 来进行释放时,就会发生内存泄漏。string 类中的内存泄漏既不在构 造函数中,也不在析构函数中。我们可以看到,在每个构造函数中仅执行一次 new,以获得一个 指向字符数组的指针,并把这个指针保存在 s 中。在 string 对象中总是包含有一个数组来存储字 符串,并且这块内存在对象生存期结束时,将会通过在析构函数中调用 delete[] s 来进行释放。

在 concat() 中存在着内存泄漏,因为在函数中分配新的数组时,并没有释放对象中当前的数 组。当 concat() 执行下面的语句时:
image

s 马上被一个新的指针值覆盖,而前一个指针值则被抛弃了,这就使得前一个指针所指向字 符数组成为了一块垃圾内存。

为了改正这个内存泄漏问题,concat() 必须保证原有的数组一定要被删除。我们在每次使用 new 时都将创建一个动态对象(在本例中是一个动态数组),对于每个动态对象,很关键的一件事就是 建立一个“所有者”——当不再需要动态内存时,所有者应该负责销毁动态对象。最简单的所有者 策略就是,将执行 new 操作的对象作为动态对象的所有者,并且必须由所有者来负责删除动态对象。 根据这个策略,string 类就必须负责删除所有在构造函数或者其他的成员函数中分配的字符数组。

对于每个 new操作,都要有相应的 delete操作。
对于 concat() 中的问题,解决方案并不像在执行 new 之前增加一条 delete[] s 语句这样简单。 下面的代码并不足以解决 concat() 中的问题:
image

上面的 concat() 中有什么样的错误?假设 x 和 y 是 string 类的实例,并且我们通过表达式 x.concat(y,x) 来调用 concat() 函数。那么,在 concat() 中,函数将通过两种方法来访问对象 x : this 指针和参数 b 都是指向 x。我们可以看到,在执行 concat() 时,x.s 指向的数组在通过 b.s 传 递给 strcpy() 之前,就已经通过 this->s 删除了。等到执行 strcpy() 时,字符数组已经释放了,甚 至还可能被 concat() 中的 new 进行了重新分配。

要改正 concat() 中的内存泄漏,delete 语句只能添加在新的字符串创建之后:
image

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

相关文章:

  • wp-query调用前几篇文章的方法
  • 《思科UCS服务器统一计算》一1.3 统一计算系统(UCS)
  • 从平凡通往伟大——大数据技术学习
  • 《UML面向对象设计基础》—第1章1.7节继承
  • 启动页广告
  • 深入理解Spark:核心思想与源码分析. 3.5 Hadoop相关配置及Executor环境变量
  • Nim各种pragma使用方法
  • 《设计工作室生存手册》—第1章1.8节设计师是守护者
  • iOS Sprite Kit教程之申请和下载证书
  • Xamarin.Android开发实践(八)
  • 《Java并发编程的艺术》一一2.4 本章小结
  • 淘宝开源分布式消息中间件Metamorphosis
  • 《Adobe After Effects CS6完全剖析》——使用用户界面
  • HDU 2222 Keywords Search(AC自动机)
  • 《深入解析IPv6(第3版)》——11.3 隧道配置
  • 【Leetcode】101. 对称二叉树
  • [译] 怎样写一个基础的编译器
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • fetch 从初识到应用
  • Javascript基础之Array数组API
  • Javascript设计模式学习之Observer(观察者)模式
  • Java的Interrupt与线程中断
  • jdbc就是这么简单
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • leetcode-27. Remove Element
  • webpack入门学习手记(二)
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 蓝海存储开关机注意事项总结
  • 排序(1):冒泡排序
  • 深入浏览器事件循环的本质
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 我与Jetbrains的这些年
  • 赢得Docker挑战最佳实践
  • 硬币翻转问题,区间操作
  • 用Python写一份独特的元宵节祝福
  • 智能合约Solidity教程-事件和日志(一)
  • 如何在招聘中考核.NET架构师
  • "无招胜有招"nbsp;史上最全的互…
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (poj1.3.2)1791(构造法模拟)
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (译) 函数式 JS #1:简介
  • (转) ns2/nam与nam实现相关的文件
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET Core Web APi类库如何内嵌运行?
  • .NET 设计模式初探
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .NET企业级应用架构设计系列之技术选型
  • .NET企业级应用架构设计系列之应用服务器