为了账号安全,请及时绑定邮箱和手机立即绑定

delete []如何知道它是一个数组?

delete []如何知道它是一个数组?

好吧,我认为我们都同意,根据所传递的内容,未定义以下代码所发生的情况,void deleteForMe(int* pointer){     delete[] pointer;}指针可能是各种各样的东西,因此delete[]对它执行无条件的操作是不确定的。但是,假设我们确实在传递数组指针,int main(){     int* arr = new int[5];     deleteForMe(arr);     return 0;}我的问题是,在这种情况下,指针是一个数组,谁知道呢?我的意思是,从语言/编译器的角度来看,它不知道arr数组指针还是指向单个int的指针。哎呀,它甚至不知道是否arr是动态创建的。但是,如果我改为执行以下操作,int main(){     int* num = new int(1);     deleteForMe(num);     return 0;}操作系统足够聪明,只能删除一个int,而不会通过删除超出该点的其余内存来进行某种类型的“杀戮狂潮”(与带有strlen和非\0终止字符串的字符串进行对比-它会一直运行直到它点击0)。那么记住这些事情是谁的工作呢?操作系统是否在后台保留某种类型的记录?(我的意思是,我意识到我在开始这篇文章时是说发生的事情是不确定的,但事实是,“杀人狂潮”的情况没有发生,因此在实际世界中有人会记住。)
查看完整描述

4 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

编译器不知道它是一个数组,而是在信任程序员。删除指向intwith 的指针delete []将导致未定义的行为。您的第二个main()示例是不安全的,即使它没有立即崩溃也是如此。


编译器确实必须跟踪需要删除多少个对象。它可以通过过度分配足够的空间来存储数组大小来实现此目的。有关更多详细信息,请参见C ++ Super FAQ。


查看完整回答
反对 回复 2019-10-05
?
动漫人物

TA贡献1815条经验 获得超10个赞

到目前为止给出的答案似乎并没有解决一个问题:如果运行时库(不是操作系统,实际上不是)可以跟踪数组中的事物数量,那么为什么我们根本需要delete[]语法?为什么不能使用单个delete表单来处理所有删除?


对此的答案可以追溯到C ++的根源,即C兼容语言(它不再是真正的努力。)Stroustrup的哲学是程序员不必为未使用的任何功能付费。如果他们不使用数组,则不必为每个分配的内存块承担对象数组的费用。


也就是说,如果您的代码只是


Foo* foo = new Foo;

那么分配给它的内存空间foo不应包含支持的数组所需的任何额外开销Foo。


由于仅设置了数组分配来承载额外的数组大小信息,因此您需要告诉运行时库在删除对象时寻找该信息。这就是为什么我们需要使用


delete[] bar;

而不只是


delete bar;

如果bar是指向数组的指针。


对于我们大多数人(包括我自己在内)来说,如今对一些额外的内存字节的烦恼似乎很古怪。但是,在某些情况下,保存几个字节(可能来自大量的内存块)可能很重要。


查看完整回答
反对 回复 2019-10-05
?
当年话下

TA贡献1890条经验 获得超9个赞

是的,操作系统将某些内容保留在“后台”中。例如,如果您运行


int* num = new int[5];

操作系统可以分配额外的4个字节,将分配的大小存储在已分配内存的前4个字节中,并返回偏移量指针(即,它将内存空间分配为1000到1024,但返回的指针指向1004,位置为1000- 1003存储分配的大小)。然后,当调用delete时,它可以在传递给它的指针之前查看4个字节,以查找分配的大小。


我相信还有其他方法可以跟踪分配的大小,但这是一种选择。


查看完整回答
反对 回复 2019-10-05
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

这与这个问题非常相似,并且包含许多您正在寻找的细节。


但是足以说,跟踪任何这些都不是操作系统的工作。实际上,运行时库或底层的内存管理器将跟踪数组的大小。通常,这是通过在前面分配额外的内存并在该位置存储数组的大小来完成的(大多数使用头节点)。


通过执行以下代码,这在某些实现中是可见的


int* pArray = new int[5];

int size = *(pArray-1);


查看完整回答
反对 回复 2019-10-05
  • 4 回答
  • 0 关注
  • 850 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信