[CPP] new delete
前言
今天我们来谈一谈CPP中很关键的两个操作 new 和 delete ,关于他们与析构函数的关系、动态分配的内存空间、new array ( new[] ) 和 delete array ( delete[] ) 配套出现的原因以及我们可能产生误解的内存泄漏的形式。
与构造析构函数的羁绊
在一般 CPP 书中,作者都会告诉读者在调用 new 来动态创建一个对象时,会先分配空间,再调用构造函数。在调用 delete 回收空间时,会先调用析构函数,再释放内存。这里我引用第一篇攻略里的 complex 类,来深入了解其内部原理。
假设我们动态创建一个 complex 对象:
Complex *p = new Complex();
编译器会将其转化为三步:
Complex *p;
void *mem = operator new ( sizeof Complex ) ; // 1 分配内存
p = static_cast<Complex*> ( mem ) ; // 2 类型转换
p->Complex::Complex(p) ; // 3 构造函数
第一步的 operator new 就是一个函数,内部会调用malloc(sizeof Complex)分配一块内存。
第二步进行类型转换,从 void 指针转为 Complex 指针。
第三步则调用 Complex 构造函数来为内存中的两个 double 赋值。其中传进去的 p 本身就是 this 指针,指向对象自己那一片内存。

我们回收资源:
delete p;
编译器会转化为两步:
Complex::~Complex(p); // 1 析构函数
operator delete(p); // 2 释放内存
第一步调用析构函数,如果类的设计者有什么事情要在析构函数里干(比如释放成员指针指向的内存),那么就去干,没有则调用默认的析构函数。
第二步的 operator delete 同上也是一个函数,内存会调用free(p);来释放对应的内存。

内存空间初探
当我们在调用 new 和 delete 时,内存空间究竟是怎么样的,认识这一点对于我们理解 new 和 delete 是很有帮助的,但是不同的编译器提高的方案略有不同,不过大体上的思想一致,本节就以 VC++ 编译器的做法来展示,g++ 类似。
给出两个例子:


其中头尾的 cookie 表示分配的内存块的大小,注意到图里不是写错了,而是 cookie 最低的一位表示这个内存块是被分配的内存块。除此之外,分配的内存块大小必须是16的倍数,这里说的是字节,所以16就是00000011。
在 delete 的时候,就是看的 cookie 的大小来释放内存,由 cookie 来显示大小,有 cookie 来释放内存块。
delete array
我们说 new array 和 delete array 就是 new[] 和 delete[] 。我们常说 new[] 必须由 delete[] 来收回空间,否则就会造成内存泄漏。那么是怎么个泄漏法呢?
首先来看一下 new[] 的内存块:


与 new 不同的是 new[] 会多出一个 field 来表示计数器,比如上面白色的部分,不过同样需要16字节对齐。
如果使用 delete[] 来回收内存,那么需要调用 n 次析构函数,再释放内存:

但是只使用 delete ,那么只会调用 1 次析构函数,但是那一块内存同样释放了。再次提醒,内存释放需要看 cookie 大小,cookie是多大,就释放多大的空间。

因此造成内存泄漏,实际上是没有调用足够次数的析构函数。所以我们知道,对于没有指针的类,光用 delete 来释放内存是完全 OK 的,但是有指针的类,会因为没有调用析构函数造成内存泄漏。
总结
我们发现,new[] 的内存块有时候不需要 delete[] 来配套使用,但是 new delete 一起使用,new[] delete[] 一起使用是基本素养。
Reference
C++面向对象高级编程, 侯捷.
[CPP] new delete的更多相关文章
- ZT c++ 中的重载全局new,delete
c++ 中的重载全局new,delete 分类: c++ 2010-08-06 10:31 116人阅读 评论(1) 收藏 举报 deletec++file编译器语言工作 最近做一个小项目,对c++又 ...
- gperftools cpp wrapper
gperftools cpp wrapper // Compile command : ${CXX} -o test_profiler.elf -DUSE_GPERFTOOLS -DDEBUG -D_ ...
- 转:面试题:“你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?”
转自:http://jeromecen1021.blog.163.com/blog/static/18851527120117274624888/ 面试题目: 地球人都知道,Java有个东西叫垃圾收集 ...
- 面试题:“你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?”
面试题目:地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样delete.free掉,你能不能谈谈: GC是在什么时候,对什么东西,做了什么事情? 以上算是三个问题,下面 ...
- Android gdb 调试
[1].终端目录设置到: proj.android[2].make文件的编译选项加上: -g -gstabs+[3].执行编译脚本: sh ./build_native.sh NDK_DEBUG=1[ ...
- Java GC 面试问题
转自:http://icyfenix.iteye.com/blog/715301 这个帖子的背景是今晚看到je上这张贴:http://www.iteye.com/topic/715256,心血来潮写下 ...
- 一个资深java面试官的“面试心得”
在公司当技术面试官几年间,从应届生到工作十几年的应聘者都遇到过.先表达一下我自己对面试的观点: 1.笔试.面试去评价一个人肯定是不够准确的,了解一个人最准确的方式就是“路遥知马力,日久见人心”.通过一 ...
- SVN快速入门笔记【转】
1. SVN版本控制软件目的 协作开发 远程开发 版本回退 2. 什么是SVN subVersion 支持平台操作 支持版本回退 3. 获取SVN软件 属于C/S结构软件(客户端与服务端) serve ...
- java GC是在什么时候,对什么东西,做了什么事情
面试题:“你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?” 面试题目:地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样delete.free掉,你 ...
随机推荐
- 打造一个简单实用的的TXT文本操作及日志框架
首先先介绍一下这个项目,该项目实现了文本写入及读取,日志写入指定文件夹或默认文件夹,日志数量控制,单个日志大小控制,通过约定的参数让用户可以用更少的代码解决问题. 1.读取文本文件方法 使用:JIYU ...
- Android ScrollView 去掉 scrollbar 和 阴影
1. 在 layout 里: android:scrollbars="none" android:overScrollMode="never" 2. 代码里 / ...
- 栈实现 C语言
最近上来写了一下栈,理解数据结构的栈. 头文件:stack.h 初始化栈结构与函数定义: #include<stdlib.h> #include <stdio.h> #incl ...
- linux安装scala环境
(安装scala的前提是已经安装好了jdk) 1.下载scala的安装包 wget https://scala-lang.org/files/archive/scala-2.11.0-M2.tgz 2 ...
- C++多线程编程二
1. 死锁与解锁: #include <iostream> #include <thread> #include <mutex> using namespace s ...
- 阿里云服务器之hexo环境搭建
上一步主要主要讲解云服务器购买和连接云服务器,以及文件的操作.本文主要讲解利用hexo搭建自己的静态博客,在服务器中建立自己的hexo博客环境,最后达到可以远程访问,以及远程git推送到github. ...
- iOS 时区获取问题
时区缩写 UTC, CST, GMT, CEST 以及转换 UTC是协调世界时(Universal Time Coordinated)英文缩写,是由国际无线电咨询委员会规定和推荐,并由国际时间局(BI ...
- POJ 2215
//package j; import java.util.*; public class Main { public static void main(String args[]){ int r; ...
- 在Eclipse平台中,搭建SpringBoot开发环境
1.查看eclipse版本号,Help->About Eclipse IDE 2.下载对应版本的STS插件 下载地址:https://spring.io/tools3/sts/all(注意版本对 ...
- 一、OPENERP 的一个demo
安装好OPENERP后,使用 ps -aux|grep openerp 从输出的内容可以得到OPENERP的安装信息, /usr/bin/python /usr/bin/openerp-server ...