在我看来,delete[]
知道动态分配数组的大小。我的问题是:有什么办法可以让我们在编码时不需要明确提供尺寸。
7 回答
delete[] 用来确定它必须处理多少项目的方法取决于实现。你无法得到它或以任何方式使用它。
阅读 C++ FAQ [16.14] 在 p = new Fred[n] 之后,编译器如何知道在 delete[] p 期间有 n 个要销毁的对象?(以及关于免费商店管理的总体思路的整个部分。)
我的问题是:有什么办法可以让我们在编码时不需要明确提供尺寸。
你不需要,你只需调用delete []
,没有大小。
编译器存储大小的方式是实现细节,没有指定。大多数将它存储在数组开始之前的某个内存中(而不是之后,正如其他人提到的那样)。
请参阅此相关问题:delete[] 如何“知道”操作数数组的大小?
编译器遵循不同的方法来存储分配的内存new
。这是我在某处读到的方法之一。
当编译器根据new
调用分配内存时,它可能会在开始时设置一个额外的字节,它将存储分配了多少内存。因此,当它遇到delete
调用时,它将使用这个存储的值来决定必须释放多少内存。
C++ 编译器具有深埋在某处的动态分配数组的大小;但是,在使用 C++ 编码时,这无法以任何方式访问 - 因此您必须在分配后将大小存储在某处。
[编辑]:虽然 Visual Studio 编译器套件的某些版本将大小存储在索引 -1 处,但这在编译器中不可信,或者在编码时根本不使用。
编辑:
由于 delete [] 需要为数组的所有元素调用析构函数,因此长度肯定必须存储在某个地方。至于为什么无法访问此内存以防止由于大小未知而导致走出阵列等错误 - 我不太确定。严格来说,静态分配的数组的长度必须在编译时知道,而动态分配的数组的长度必须由运行时存储,因此在这两种情况下,缓冲区溢出错误理论上都是 100% 可以预防的,但静态和动态数组都是不安全。我的猜测是这是出于性能目的,边界检查会使其变慢,原始(C 风格)数组在零安全性下提供最佳性能。
这个的实现因编译器和运行时供应商而异,可能有一些实现它可能是可访问和可用的,但它不会被视为标准和推荐的做法。要存储的长度的逻辑位置是分配的内存片段的标头中的某个位置,在您将为数组的第一个元素获得的实际地址之前。
我认为它依赖于编译器,您无法获取它供您的应用程序使用。以下链接显示了编译器使用的 2 种方法。
http://www.parashift.com/c++-faq-lite/compiler-dependencies.html#faq-38.7
http://www.parashift.com/c++-faq-lite/compiler-dependencies.html#faq-38.8