由同事推荐的一篇博客:

为何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[]都能正确释放的更多相关文章

  1. delete和delete[] 区别

    // DeleteAndDelete[].cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows.h> ...

  2. 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( ...

  3. [skill] C++ delete VS delete []

    delete 用来删除 new 返回的对象. 先调用对象的析构,然后释放指针指向的内存. delete[] 用来删除 new [] 返回的对象. 先调用数组中每一个对象的析构,然后释放指针指向的内存.

  4. 【转】 C++中delete和delete[]的区别

    一直对C++中的delete和delete[]的区别不甚了解,今天遇到了,上网查了一下,得出了结论.做个备份,以免丢失. C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete ...

  5. C++:delete和delete[]释放内存的区别

      C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[].  关于 new[] 和 delete[], ...

  6. C++中delete和delete[]的区别

    C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]. 关于 new[] 和 delete[],其中又 ...

  7. 关于delete和delete[]

    [精彩] 求问delete和delete[] 的区别??http://www.chinaunix.net/jh/23/311058.html C++告诉我们在回收用 new 分配的单个对象的内存空间的 ...

  8. C++中delete和delete[]的使用

    偶然的机会要使用到动态分配整形数组,怎么删除new出来的东西一时有点模糊(也许一直就不知道),于是在VS上试了试(写代码时经常用这种方法去验证模凌两可的东西),总结出来有两点. 1.基本数据类型new ...

  9. C++中delete 和delete[]的区别

    c++告诉我们在回收new分配的单个对象的内存空间的时候用delete,   回收new[ ]分配的一组对象的内存空间的时候用 delete[ ]; #include <iostream> ...

随机推荐

  1. json文件报expected name at 1 1错误

    在eclipse编辑json文件时出现expected name at 1 1错误,解决方式如下: 方法一:json文件是不支持注释的,把所有/* content */删除即可 如果不想删除注释-- ...

  2. Js-Html 前端系列--Ajax

    最近在做Web项目,用到很多Ajax,也遇到很多问题.下面与大家分享. Ajax传参 Ajax同步与异步 Ajax与谷歌浏览器 Ajax传参 我们一般传参有两种形式: $.ajax({ ... dat ...

  3. [ios2]ios RSA

    http://blog.iamzsx.me/show.html?id=155002 http://www.theosoft.net/ http://blog.sina.com.cn/s/blog_5f ...

  4. JavaScript的对象与Json

    JSON有非常严格的语法,在string上下文里{ "prop": "val" } 是个合法的JSON,但{ prop: "val" }和{ ...

  5. 安装windows后grub的恢复

    问题: 原本是:双系统(linux和windows),后来换windows版本覆盖了grub2 解决方法: 进入windows后下载并安装EasyBCD并添加grub2的选项,重启看见了熟悉的启动项, ...

  6. python 2.7 字符串处理

    python 2 字符串处理小结: 字符替换:new_str = old_str.replace(char_old, char_new)--可用于清除字符串中所有的空格 字符分割(正/反):str_n ...

  7. linux添加swap

    一. 起因 发现云服务器重装后没有swap分区 于是我们分出一些物理内存做swap分区.. 二. 经过 (1)创建块文件 sudo dd if=/dev/zero of=/tmp/big_swap b ...

  8. sql Cursor的用法

    table1结构如下 id int name ) declare @id int ) declare cursor1 cursor for --定义游标cursor1 select * from ta ...

  9. Java中修饰符

    下面这张图应该大家都见过,根据图表来记忆最好理解 范围 private friendly(默认) protected public 当前类 √ √ √ √ 当前包中的类   √ √ √ 当前包中的类, ...

  10. C#带参数打开网页及url获取

    1.带参数打开网页 Response.Redirect("form2.aspx?id=url1&name=ok"); 其中?后面为参数. 2.获取url 命令 结果 Req ...