为什么new的普通数组用delete 和 delete[]都能正确释放

时间:2021-12-19 12:33:29

由同事推荐的一篇博客:

为何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&lbrack;&rsqb; 区别

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

  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. &lbrack;skill&rsqb; C&plus;&plus; delete VS delete &lbrack;&rsqb;

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

  4. 【转】 C&plus;&plus;中delete和delete&lbrack;&rsqb;的区别

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

  5. C&plus;&plus;:delete和delete&lbrack;&rsqb;释放内存的区别

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

  6. C&plus;&plus;中delete和delete&lbrack;&rsqb;的区别

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

  7. 关于delete和delete&lbrack;&rsqb;

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

  8. C&plus;&plus;中delete和delete&lbrack;&rsqb;的使用

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

  9. C&plus;&plus;中delete 和delete&lbrack;&rsqb;的区别

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

随机推荐

  1. Chrome谷歌浏览器下不支持css字体小于12px的解决办法

    先来看下 ie.火狐.谷歌浏览器下各个字体显示情况 ie下: 火狐下: 谷歌下: 从上面的图可以很明显看出谷歌下 css设置字体大小为12px及以下时,显示都是一样大小,都是默认12px; 那么网上一 ...

  2. Eclipse安装easyShell插件

    easyshell是一个用于快速打开文件目录.复制文件路径.cmd打开等等的eclipse插件工具. Eclipse下安装easyshell: 1.打开Eclipse商店 2.输入easyShell点 ...

  3. Could not get BatchedBridge&comma; make sure your bundle is packaged correctly

    react-native 运行android项目的时候运行成功但是模拟器上会提示: Could not get BatchedBridge, make sure your bundle is pack ...

  4. iOS UITableView点击按钮滚到顶部

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

  5. IIS修改队列长度&lpar;IIS6&plus;IIS7&rpar;

    Internet Information Services (IIS) 限制了在任何给定时间可在队列中等待的应用程序池请求的最大数量.如果达到此限制,则所有新请求都将被拒绝,而且用户将收到错误消息“5 ...

  6. 文本编辑器Nano实用快捷键

    一.复制.剪切和粘贴文本 1.行复制.剪切和粘贴 Alt+6:复制光标所在行. Ctrl+K:剪切光标所在行. Ctrl+U:粘贴. 2.*复制.剪切和粘贴 *复制: Ctrl+6:设置复制文本的 ...

  7. HDOJ&lpar;HDU&rpar; 1408 盐水的故事

    Problem Description 挂盐水的时候,如果滴起来有规律,先是滴一滴,停一下:然后滴二滴,停一下:再滴三滴,停一下-,现在有一个问题:这瓶盐水一共有VUL毫升,每一滴是D毫升,每一滴的速 ...

  8. &quot&semi;fatal&colon; protocol error&colon; bad line length character&colon; No This&quot&semi;

    git clone 远程地址时候出现 "fatal: protocol error: bad line length character: No This" 错误 在stackov ...

  9. python--Numpy and Pandas 基本语法

    numpy和pandas是python进行数据分析的非常简洁方便的工具,话不多说,下面先简单介绍一些关于他们入门的一些知识.下面我尽量通过一些简单的代码来解释一下他们该怎么使用.以下内容并不是系统的知 ...

  10. Linux查看日志工具

    ⒈journalctl journalctl是Centos7才有的工具用于systemd统一管理所有unit的启动日志,只用一个journalctl命令就可以查看所有的日志(包括内核日志和应用日志), ...