为什么new的普通数组用delete 和 delete[]都能正确释放
由同事推荐的一篇博客:
为何new出的对象数组必须要用delete[]删除,而普通数组delete和delete[]都一样-------_CrtMemBlockHeader
文章解释了delete 内部是怎么操作的,讲解也很生动形象。不过看了以后,我只知道了对象数组 用 delete 为什么不行,但是还是不知道普通数组为什么可以用delete[];
文章问的不正确,应该是 为何new出的有析构函数的对象数组必须要用delete[]删除。
经过试验,只有 new 有析构函数(不管是程序员显式定义的 还是由编译器创建的nontrival的析构函数(《深度探索C++对象模型》)) 的对象数组才会记录对象个数。普通数组和没有析构函数的对象数组都不会。
而这就是要记录对象数组个数的原因,就是为了要执行析构函数。就要要知道要执行几次析构函数。
是要定义 delete [] 的原因,就是为了迎合 c++ 的 class 的析构函数的执行。
为什么普通数组释放 delete 和 delete[] 都一样
没有找到delete[]的具体实现 调试也进不去 所以下面的都是我猜想的==,根据上面那篇文章
delete 是默认调用一次析构函数,如果有需要调用的话;
但是delete[] 是根据 存的数组个数 调用几次析构函数,当然如果没有存对象数组的个数,也就不需要调用析构函数了。
如果是delete p;
不管p是什么 都把指针往前移动多少 8*4个字节,在清空内存之前 会先判断某个值是不是对的。
如果是delete[] p;
是不是先检查p是不是有析构函数的对象数组,
如果是的话就往前移动 9*4个字节,然后将前8*4个字节当作头,将 (数组元素个数+<yout data>)整个数据当成 pUserData,然后再进行析构函数的调用 和 一次性释放内存。
如果不是的话,就调用delete p;
为什么 new[]/delete[] 需要记录对象个数?
作者:陈硕
链接:https://zhuanlan.zhihu.com/p/22455100
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
对于有 non-trivial destructor 的 class T, 现在通常的 C++ 实现会在 new[] 的时候多分配 sizeof(size_t) 字节用于保存数组大小,
在 delete[] 的时候会依次逆序调用数组中各对象的析构函数。有的文献管这多分配的几个字节叫 new cookie (Itanium C++ ABI)。
那或许有人会问,既然根据数组首地址就能知道分配了多少字节内存,那为什么 new[] 还需要再保存对象的数目?
这不是多余吗?直接用 内存长度 / sizeof(T) 不就可以算出需要析构多少个对象了?
原因很简单:
内存长度 / sizeof(T) >= 对象个数
因为 new / malloc 在分配内存的时候会 round up 到某个数的倍数(8 或 16 等,跟 malloc 具体实现有关),
即 内存长度 = round_up(sizeof(T) * 对象个数),那么反过来我们就不能用内存长度算出对象个数了,必须单独保存对象个数。
假如不采用 new cookie,如果 sizeof(Foo) == 4,那么 Foo* p = new Foo[28];
会分配 112 字节来构造 28 个对象,但实际会从 libc 拿到 116 字节,那么 delete[] p; 会析构 116/4 = 29 个对象,这就有大问题了。
因此,通常的 C++ 实现在必要时会在 new[] 的时候多分配 sizeof(size_t) 字节用于保存对象数目,而不是让 delete[] 依靠内存大小来算出需要析构多少个对象。
还看了一篇 可以参考下:
浅谈 C++ 中的 new/delete 和 new[]/delete[]
为什么new的普通数组用delete 和 delete[]都能正确释放的更多相关文章
- delete和delete[] 区别
// DeleteAndDelete[].cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows.h> ...
- js中数组删除 splice和delete的区别,以及delete的使用
var test=[];test[1]={name:'1',age:1};test[2]={name:'2',age:2};test[4]={name:'3',age:3}; console.log( ...
- [skill] C++ delete VS delete []
delete 用来删除 new 返回的对象. 先调用对象的析构,然后释放指针指向的内存. delete[] 用来删除 new [] 返回的对象. 先调用数组中每一个对象的析构,然后释放指针指向的内存.
- 【转】 C++中delete和delete[]的区别
一直对C++中的delete和delete[]的区别不甚了解,今天遇到了,上网查了一下,得出了结论.做个备份,以免丢失. C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete ...
- C++:delete和delete[]释放内存的区别
C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]. 关于 new[] 和 delete[], ...
- C++中delete和delete[]的区别
C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]. 关于 new[] 和 delete[],其中又 ...
- 关于delete和delete[]
[精彩] 求问delete和delete[] 的区别??http://www.chinaunix.net/jh/23/311058.html C++告诉我们在回收用 new 分配的单个对象的内存空间的 ...
- C++中delete和delete[]的使用
偶然的机会要使用到动态分配整形数组,怎么删除new出来的东西一时有点模糊(也许一直就不知道),于是在VS上试了试(写代码时经常用这种方法去验证模凌两可的东西),总结出来有两点. 1.基本数据类型new ...
- C++中delete 和delete[]的区别
c++告诉我们在回收new分配的单个对象的内存空间的时候用delete, 回收new[ ]分配的一组对象的内存空间的时候用 delete[ ]; #include <iostream> ...
随机推荐
- 由自动装箱和拆箱引发我看Integer源码
背景和问题 在看别人整理的资料时,看到如下一段代码: package com.sitech.test; /** * 自动装箱和拆箱 jdk1.6 * @author liaowp * */ publi ...
- android中使用Http下载文件并保存到本地SD卡
1.AndroidMainfest.xml中设置权限 <uses-permission android:name="android.permission.INTERNET"& ...
- Linux中top和free命令详解(转)
top:命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最"敏感"的任务列表. 该命令可以按CPU使用.内存使用和执行时间对任务进行排序: 而且该命令的很多特性都可以通 ...
- Windows设置VMware开机自动启动,虚拟机也启动
很多用windows系统电脑开发的童鞋,会在自己电脑上装一个虚拟机,然后在装一个linux系统当作服务器来使用.但每次电脑开机都要去重启一下虚拟机电源,实在是不划算.下面博主教大家在windows系统 ...
- Linux环境快速部署Zookeeper集群
一.部署前准备: 1.下载ZooKeeper的安装包: http://zookeeper.apache.org/releases.html 我下载的版本是zookeeper-3.4.9. 2.将下载的 ...
- mac nodejs安装
很久没有配置开发环境了,刚换了新电脑,正好借机会重新配置一下node相关的开发环境 安装 nvm :Node Version Manager 由于nodejs版本更新迭代较快,而不同版本间的差异又很大 ...
- MyBatis 学习-与 Spring 集成篇
根据官方的说法,在 ibatis3,也就是 Mybatis3 问世之前,Spring3 的开发工作就已经完成了,所以 Spring3 中还是没有对 Mybatis3 的支持.因此由 Mybatis 社 ...
- How I Mathematician Wonder What You Are!(poj 3130)
题意:求问多边形的核(能够看到所有点的点)是否存在. /* 对于这样的题目,我只能面向std编程了,然而还是不理解. 算法可参考:http://www.cnblogs.com/huangxf/p/40 ...
- Python学习笔记——基础篇【第五周】——正则表达式(re)
目录 1.简介 2.字符匹配 1.简介:就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现.正则表达式模式被编译 ...
- java 生成条形码
package com.sun.erwei; import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;impo ...