第八章 定制new和delete

对于程序开发来说,了解C++内存管理例程的行为是非常重要的。其中两个主角是分配例程和归还例程(operator newoperator delete),配角是new-handker,这是当operator new无法满足客户的内存需求时所调用的函数。

注意STL容器所使用的heap内存是由容器所拥有的分配器对象(allocator objects)管理,不是被newdelete直接管理。

条款49:了解new-hander的行为

请记住

  • set_new_handler允许客户指定一个函数,在内存分配无法获得满足时被调用。
  • Nothrow new是一个颇为局限的工具,因为它只适用于内存分配;后继的构造函数调用还是可能抛出异常。

条款50:了解newdelete的合理替换机制

一般处于下列原因可能想要替换编译器提供的operator newoperator delete

  • 为了检测运用错误。
  • 为了收集动态分配内存的使用统计信息。
  • 为了增加分配和归还的速度。
  • 为了降低缺省内存管理器带来的空间额外开销。
  • 为了弥补缺省分配器中的非最佳齐位。
  • 为了将相关对象成簇集中。
  • 为了获得非传统的行为。

下面是一个”为了检测运用错误“而实现的简单的 operator new 的例子,通过在首部和尾部插入一个签名,返回中间内存块给程序使用,如果程序在使用内存时发生过在区块前或区块后写入的行为,那么签名就会被修改,因此可以检测这种行为:

static const int signature = 0xDEADBEEF; // 边界符
typedef unsigned char Byte;
void* operator new(std::size_t size) throw(std::bad_alloc) {
// 多申请一些内存来存放占位符
size_t realSize = size + 2 * sizeof(int);
// 申请内存
void *pMem = malloc(realSize);
if (!pMem) throw bad_alloc();
// 写入边界符
*(reinterpret_cast<int*>(static_cast<Byte*>(pMem)+realSize-sizeof(int)))= *(static_cast<int*>(pMem)) = signature;
// 返回真正的内存区域
return static_cast<Byte*>(pMem) + sizeof(int);
}

这个例子主要是展示,它存在很多错误:

  • 所有的 operator new 都应该内含一个循环,反复调用某个 new-handling 函数,这里却没有。
  • C++要求所有 operator new 返回的指针都有适当的对齐。这里 malloc 返回的指针是满足要求的,但是因为上述实现并不是直接返回 malloc 的结果,而是返回一个 int 偏移后的地址,因此无法保证它的安全。

请记住

  • 有许多理由需要自定的newdelete,包括改善效能、对heap运用错误进行调试、手机heap使用信息。

条款51:编写newdelete时需固守常规

请记住

  • operator new应该包含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存要求,就该调用new-handler。它也应该有能力处理0bytes申请。Class专属版本则还应该处理"比正确大小更大的(错误)申请"。
  • operator delete应该在收到null指针时不做任何事。Class专属版本则还应该处理"比正确大小更大的(错误)申请"。

条款52:写了placement new也要写placement delete

请记住

  • 当你写一个placement operator new,请确定也写出类对应的placement operator delete。如果没有这样做,你的程序可能会发生隐蔽而时断时续的内存泄漏。
  • 当你声明placement newplacement delete,请确定不要无意识(非故意)地遮掩了它们的正常版本。

【C++】《Effective C++》第八章的更多相关文章

  1. 【C++】《C++ Primer 》第十八章

    第十八章 用于大型程序的工具 大规模应用程序的特殊要求包括: 在独立开发的子系统之间协同处理错误的能力. 使用各种库进行协同开发的能力. 对比较复杂的应用概念建模的能力. 一.异常处理 异常处理(ex ...

  2. c++ primer plus(文章6版本)中国版 编程练习答案第八章

    编程练习答案第八章 8.1写输出字符串的函数,存在默认参数表示输出频率,莫感觉1.(原标题太扯了,的问题的细微变化的基础上,含义) //8.1编写一个输出字符串的函数.有一个默认參数表示输出次数,默觉 ...

  3. C++ Primer Plus学习:第八章

    C++入门第八章:函数探幽 本章将介绍C++语言区别于C语言的新特性.包括内联函数.按引用传递变量.默认的参数值.函数重载以及函数模板. 1 C++内联函数 内联函数是C++为提高程序运行速度所做的一 ...

  4. 【C++】《C++ Primer 》第八章

    第八章 IO库 一.IO类 1. 标准库定义的IO类型 头文件 作用 类型 iostream 从标准流中读写数据 istream, wistream 从流读取数据 ostream, wostream ...

  5. C++Primer 第十八章

    //1.异常:待研究 //2.命名空间: // A:多个库将名字放置在全局命名空间中将引发命名空间污染. // B:命名空间为防止名字冲突提供了更加可控的机制.命名空间分割了全局命名空间,其中每个命名 ...

  6. C++ Primer:第八章:IO库(续)

    二:文件输入输出. (1) 使用文件流对象: 头文件fstream定义了三个类型来支持文件IO:ifstream从一个给定的文件中读取数据,ofstream向一个给定的文件中写入数据,以及fstrea ...

  7. C primer plus 读书笔记第八章

    本章的标题是字符输入/输出和输入确认.主要内容是讨论用于I/O的标准函数. 1.getchar()和putchar() 这两个函数之前用过,我们通过这两个函数来讨论下缓冲区. #include &qu ...

  8. C++ primer 中文第三版 阅读笔记 第八章

    一.寄存器对象: 函数中频繁被使用的变量可以加上register就可声明为寄存器对象.对于寄存器对象,假如能够放到寄存器中就会放到寄存器中,放不到的话就放到内存中.比如 register int  a ...

  9. C++ Primer的课后规划问题的第八章

    1.写通常需要一个参数(字符串的地址).字符串和打印功能. 只要.假设提供了第二个参数(int种类),而这个参数不0,的次数的函数打印串数量为该功能将被称为(意,字符串的打印次数不等于第二个參数的值. ...

  10. c primer plus(五版)编程练习-第八章编程练习

    1.设计一个程序,统计从输入到文件结尾为止的字符数. #include<stdio.h> int main(void){ int ch; int i; i=; while((ch = ge ...

随机推荐

  1. 题解-Sakuya's task

    题面 Sakuya's task \[\left(\sum_{i=1}^n\sum_{j=1}^n \varphi(\gcd(i,j))\right)\bmod 10^9+7 \] 数据范围:\(1\ ...

  2. HDU3306 Another kind of Fibonacci

    本篇题解用于作者本人对于矩阵乘法的印象加深,也欢迎大家的阅读. 题目大意 众所周知,斐波那契数列为 \(f(0)=1\) , \(f(1)=1\) ,\(f(n)=f(n-1)+f(n-2)~(n&g ...

  3. 第三方模块Gulp

    1.第三方模块Gulp 基于node平台开发的前端构建工具. 将机械化操作编写成任务,想要执行机械化操作时执行一个命令,命令任务就能自动执行了.提高开发效率. 1)Gulp使用 ① 使用npm ins ...

  4. Java并发编程的艺术(四)——JMM、重排序、happens-before

    什么是JMM JMM就是Java内存模型.目的是为了屏蔽系统和硬件的差异,让同一代码在不同平台下能够达到相同的访问结果.规定了线程和内存之间的关系. 内存划分 JMM规定了内存主要划分为主内存和工作内 ...

  5. 大白话详解大数据hive知识点,老刘真的很用心(2)

    前言:老刘不敢说写的有多好,但敢保证尽量用大白话把自己复习的内容详细解释出来,拒绝资料上的生搬硬套,做到有自己的了解! 1. hive知识点(2) 第12点:hive分桶表 hive知识点主要偏实践, ...

  6. WebService-问题

    1.引用问题 在用C#对接webservice的时候,常用的方法是下载vs中引用webservice的地址.然后,new对应的client就可以使用了.但在,实际应用中往往会遇到webservice访 ...

  7. 在线CC攻击网站源码

    源码目录 index.html 首页 cc.php 核心文件 count.php 使用统计 pv.php 访问测试页面 ip.txt 代理IP数据文件 运行方式 域名/?url=目标网址 要先获取代{ ...

  8. 使用OpenSSL自建一个HTTPS服务

    1. 理论知识 1.1 什么是https 传统的 HTTP 协议以明文方式进行通信,不提供任何方式的数据加密,很容易被中间攻击者破解通信内容或者伪装成服务器与客户端通信,在安全性上存在很大问题. HT ...

  9. 【C#】DockPanelSuite 中 DockState.Document 状态下子窗体控件不显示的解决方案

    DockPanelSuite 是 Winform 中优秀的布局控件,但是这次使用过程中却出了个问题. 我遇到的问题是这样的,主窗体是通过 ShowDialog 显示的,子窗体的停靠状态为 DockSt ...

  10. 史上最全Xshell and Xftp 工具的使用

    文章目录 什么是xshell 解决: 安装Xshell Xshell怎么建立连接 Xshell如果修改已有连接信息? 修改,背景色,字体,编码 Xshell导出已有的登录信息 Xftp的使用 XFP建 ...