既然xxx* p = new xxx[20] 要用delete[]释放,为什么还允许 delete p;通过编译?

bandaoyu 2020-04-01 10:04:23
既然xxx* p = new xxx[20] 要用delete[]释放,为什么还允许 delete p;通过编译?

比如:
char* p = new char[20];
delete p;

编译没有报错
...全文
2193 67 打赏 收藏 转发到动态 举报
写回复
用AI写文章
67 条回复
切换为时间正序
请发表友善的回复…
发表回复
待续_1006 2020-04-07
  • 打赏
  • 举报
回复
想问下各位大神,这是人家制定的标准,如果你是C++委员会的,规则你来制定,这有讨论的必要吗。。。。。。。。。
zy010101 2020-04-04
  • 打赏
  • 举报
回复
引用 7 楼 bandaoyu的回复:
引用 6 楼 棉猴 的回复:
对呀,行为未定义编译器为什么给通过呢?
未定义不就是交给编译器厂商设计去吧。编译器厂商想设计成什么样就设计成什么样!
  • 打赏
  • 举报
回复
删除引用。。。浅拷贝,深拷贝,地址。。。数组也是个引用啊,你删除p这个指针和删除p指向的数组,两回事儿啊
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
一个语言的正确性,就是只要程序员做的符合他的规则,必然不能出错,你无法保证之前的信息的正确性,那么就是程序是对的,结果却是错的。
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
引用 60 楼 早打大打打核战争 的回复:
[quote=引用 59 楼 真相重于对错 的回复:] [quote=引用 58 楼 早打大打打核战争 的回复:] delete[]为什么不需要你告诉它要释放的数组有多大?是因为它知道这个信息,这个信息并不是编译时确定的,而是运行时检查new[]在分配块之前的信息头中保存的信息,你好好理解一下~~~
我从来没说那是编译时期确定,你要运行时候检查,你如何确定,那个信息一定是正确的?????[/quote] 你这就属于抬杠了,现在的delete[]实现就是要检查分配块之前的信息头,你说它怎么保证?显然不可能保证“那个信息一定是正确的”,只能尽量保证,比如先验证一下是否是有效的分配块,拿待删除的指针和保存在分配块之前的信息头中的指针比对一下 [/quote] 这怎么是抬杠呢?要去掉delete[] ,那么必然要有信息好让delete 判断,那么不管是单个对象指针还是数组指针,都要有一个存储这个信息的地方。对不? 好了,我再举个例子如果是placement new怎么办?去掉这个语言特性。。。。。。。。。
  • 打赏
  • 举报
回复
引用 59 楼 真相重于对错 的回复:
[quote=引用 58 楼 早打大打打核战争 的回复:]
delete[]为什么不需要你告诉它要释放的数组有多大?是因为它知道这个信息,这个信息并不是编译时确定的,而是运行时检查new[]在分配块之前的信息头中保存的信息,你好好理解一下~~~

我从来没说那是编译时期确定,你要运行时候检查,你如何确定,那个信息一定是正确的?????[/quote]

你这就属于抬杠了,现在的delete[]实现就是要检查分配块之前的信息头,你说它怎么保证?显然不可能保证“那个信息一定是正确的”,只能尽量保证,比如先验证一下是否是有效的分配块,拿待删除的指针和保存在分配块之前的信息头中的指针比对一下
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
引用 58 楼 早打大打打核战争 的回复:
delete[]为什么不需要你告诉它要释放的数组有多大?是因为它知道这个信息,这个信息并不是编译时确定的,而是运行时检查new[]在分配块之前的信息头中保存的信息,你好好理解一下~~~
我从来没说那是编译时期确定,你要运行时候检查,你如何确定,那个信息一定是正确的?????
  • 打赏
  • 举报
回复
delete[]为什么不需要你告诉它要释放的数组有多大?是因为它知道这个信息,这个信息并不是编译时确定的,而是运行时检查new[]在分配块之前的信息头中保存的信息,你好好理解一下~~~
taodm 2020-04-03
  • 打赏
  • 举报
回复
这个问题都能讨论那么多? C++标准94年基本成熟,98年标准化。我学C++的时候,还是用的比尔.盖茨的“640K内存对谁都够了”的级别的电脑 那个说delete也可以记录元素个数的兄弟,640k内存,你这得多少浪费率? VC长期就只有delete[],没有真正的delete版本,所以,那个说必须有2个版本的,其实对于现在的计算机,这真不是个事儿,内存和效率的损失都可以无视的。 另外说个事儿,我学C++的时候,不但要delete [],还要在[]里自己写出当初申请的个数,要delete [10] p
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
为什么C++必须有,前面我讲的太多,我不想多说了。。。。。
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
c++ 还真不能没有new[] delet[] 配对。。。。。。
引用 54 楼 早打大打打核战争 的回复:
[quote=引用 52 楼 真相重于对错 的回复:] [quote=引用 51 楼 早打大打打核战争 的回复:] 没有误解,我说的是delete和delete[]都要检查待释放的分配块前的信息头,这一步是少不了的,否则不可能正确释放。注意我说的是从语言设计角度完全可以不需要delete[],而不是当前实现,当前实现delete和delete[]肯定是有区别的。
你的语言的意思,是指c++吗?还是另外一门语言。。。。。。。[/quote] 不管是C++还是其他有指针语言,只要实现了new/delete类似功能的都适用。这只是一个设计问题,很多时候现状只是历史遗留问题的反映,而不代表现状就是对的或者最好,好比Dennis Ritchie在1982就承认C语言运算符优先级设计有问题,但是已经积累了很多代码,无法修改了。 [/quote]
  • 打赏
  • 举报
回复
引用 52 楼 真相重于对错 的回复:
[quote=引用 51 楼 早打大打打核战争 的回复:]
没有误解,我说的是delete和delete[]都要检查待释放的分配块前的信息头,这一步是少不了的,否则不可能正确释放。注意我说的是从语言设计角度完全可以不需要delete[],而不是当前实现,当前实现delete和delete[]肯定是有区别的。

你的语言的意思,是指c++吗?还是另外一门语言。。。。。。。[/quote]

不管是C++还是其他有指针语言,只要实现了new/delete类似功能的都适用。这只是一个设计问题,很多时候现状只是历史遗留问题的反映,而不代表现状就是对的或者最好,好比Dennis Ritchie在1982就承认C语言运算符优先级设计有问题,但是已经积累了很多代码,无法修改了。
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
如果说的不是c++的话,那么其实delete都没必要,十几年前的c#,java,一般都不需要delete.
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
引用 51 楼 早打大打打核战争 的回复:
没有误解,我说的是delete和delete[]都要检查待释放的分配块前的信息头,这一步是少不了的,否则不可能正确释放。注意我说的是从语言设计角度完全可以不需要delete[],而不是当前实现,当前实现delete和delete[]肯定是有区别的。
你的语言的意思,是指c++吗?还是另外一门语言。。。。。。。
  • 打赏
  • 举报
回复
没有误解,我说的是delete和delete[]都要检查待释放的分配块前的信息头,这一步是少不了的,否则不可能正确释放。注意我说的是从语言设计角度完全可以不需要delete[],而不是当前实现,当前实现delete和delete[]肯定是有区别的。
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
如果你的想法正确,c++标准委员会,应该把你请去。。。。。
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
不是delete delete[] 都要检查。 delete 不用 直接调用析构函数,再回收内存 delete [] 才需要,然后依次数组内的对象的析构函数。再回收内存 如果是平凡类型,则delete 和 delete[] 没区别
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
引用 47 楼 早打大打打核战争 的回复:
[quote=引用 46 楼 真相重于对错 的回复:] [quote=引用 45 楼 早打大打打核战争 的回复:] 实际上内存分配块之前的信息头远不止4字节,可能多达几十字节,里面还有分配块的指针用于验证,否则随便传个指针delete/delete[]就瞎释放,把整个堆的分配链都破坏了。
但是没有new[] 和 delete[] 配对,则你不可能保证,每次都是正确的。[/quote] 从设计角度来说,delete[]就是多余的,是设计者一种强迫症的反映,认为有new[]就应该有delete[],否则不对称了心里不舒服。实际上不管是new还是new[]都要设置分配块前的信息头,delete和delete[]都要检查信息头,释放一个对象和释放一数组对象技术上没有区别,完全可以只用delete实现两者的功能而不需要delete[](注意我说的是逻辑而不是当前实现)。 [/quote]你是不是对delete[],有误解啊 我给你举个例子 struct X{ char* ptr; X():ptr(nullptr){} X(const char*){....} ~X(){ delete ptr; } }; X* p = new X("123"); X* array = new X[10]; delete p; delete [] array;
  • 打赏
  • 举报
回复
引用 46 楼 真相重于对错 的回复:
[quote=引用 45 楼 早打大打打核战争 的回复:]
实际上内存分配块之前的信息头远不止4字节,可能多达几十字节,里面还有分配块的指针用于验证,否则随便传个指针delete/delete[]就瞎释放,把整个堆的分配链都破坏了。

但是没有new[] 和 delete[] 配对,则你不可能保证,每次都是正确的。[/quote]

从设计角度来说,delete[]就是多余的,是设计者一种强迫症的反映,认为有new[]就应该有delete[],否则不对称了心里不舒服。实际上不管是new还是new[]都要设置分配块前的信息头,delete和delete[]都要检查信息头,释放一个对象和释放一数组对象技术上没有区别,完全可以只用delete实现两者的功能而不需要delete[](注意我说的是逻辑而不是当前实现)。
真相重于对错 2020-04-03
  • 打赏
  • 举报
回复
引用 45 楼 早打大打打核战争 的回复:
实际上内存分配块之前的信息头远不止4字节,可能多达几十字节,里面还有分配块的指针用于验证,否则随便传个指针delete/delete[]就瞎释放,把整个堆的分配链都破坏了。
但是没有new[] 和 delete[] 配对,则你不可能保证,每次都是正确的。
加载更多回复(47)
设备树(device tree)机制是Linux内核从linux-3.x版本开始引进的一种机制,目的是解决内核源码的arch/arm目录下代码混乱的问题:随着ARM生态的快速发展,在内核源码的arch/arm目录下,存放着几十种arm芯片和几百个开发板相关的源文件,很多开发板和处理器的中断、寄存器等相关硬件资源都在这个目录下以.c或.h的文件格式定义。而对于内核来说,与这些硬件耦合,会导致内核代码混乱不堪,每个开发板上运行的内核镜像都必须单独编译配置,无法通用。什么时候Linux内核能像Windows镜像那样,无论你的电脑什么配置,一个Windows安装包,都可以直接下载安装运行呢?设备树机制,实现了Linux内核和硬件平台的解耦:每个硬件平台的硬件资源使用一个设备树文件(xxx.dts)来描述,而不是在arch/arm下以.c 或 .h 文件来定义。Linux内核是一个通用的内核,在启动过程中,在通过解析设备树中的硬件资源来初始化某个具体的平台。 引入设备树后,很多和内核驱动开发的工作也发生了变化:以往驱动工程师关注的头文件宏定义、寄存器定义,现在这些基本上不用关注,关注的重点则转向了如何根据硬件平台去配置和修改设备树文件。很多驱动的编程接口也发生了变化,开始慢慢使用device tree提供的编程接口去开发驱动。本期课程主要面向嵌入式开发人员,分享Linux下驱动开发所需要的设备树知识和必备技能

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧