为什么无法访问新[]'d数组的大小?

时间:2010-03-09 00:06:54

标签: c++ arrays new-operator delete-operator

使用new []分配数组时,为什么不能从指针中找出该数组的大小?它必须在运行时知道,否则delete []将不知道要释放多少内存。

除非我遗漏了什么?

4 个答案:

答案 0 :(得分:15)

在典型的实现中,动态内存块的大小以某种方式存储在块本身中 - 这是真的。但是没有标准的方法来访问这些信息。 (实现可以提供特定于实现的访问方式)。这就是malloc/free的用法,new[]/delete[]就是这样。

事实上,在典型的实现中,new[]/delete[]调用的原始内存分配最终由某些特定于实现的malloc/free对处理,这意味着delete[]实际上没有关心要释放多少内存:它只是调用内部free(或其命名的任何内容),它负责处理。

delete[]确实需要知道的是,当数组元素类型具有非平凡的析构函数时, destruct 有多少元素。这就是你的问题 - 数组元素的数量,而不是块的大小(这两个不一样,块可能比数组本身真正需要的大)。因此,数组中元素的数量通常也会被new[]存储在块内部,然后由delete[]检索以执行正确的数组元素销毁。没有标准方法可以访问此号码。

(这意味着在一般情况下,由new[]分配的典型内存块将独立地同时存储两者物理块大小,以字节为单位数组元素计数。这些值由不同级别的C ++内存分配机制存储 - 原始内存分配器和new[]本身 - 并且不以任何方式相互交互。)

但是,请注意,由于上述原因,数组元素计数通常仅在数组元素类型具有非平凡的析构函数时存储。即这个计数并不总是存在。这是为什么提供访问数据的标准方法不可行的原因之一:您必须始终存储它(浪费内存)或通过析构函数类型限制其可用性(这令人困惑)。

为了说明上述内容,当您创建int s

的数组时
int *array = new int[100];

数组的大小(即100 not 通常由new[]存储,因为delete[]并不关心它(int没有析构函数)。块的物理大小(以400字节或更多字节为单位)通常由原始内存分配器存储在块中(由delete[]调用的原始内存释放器使用),但它很容易变成由于某些特定于实现的原因而为420。所以,这个大小对你来说基本没用,因为你无法从中获得精确的原始数组大小。

答案 1 :(得分:7)

您最有可能访问它,但它需要您对分配器的深入了解,并且不可移植。 C ++标准没有指定 实现如何存储此数据,因此没有一致的方法来获取它。我认为它没有具体说明,因为不同的分配器可能希望以不同的方式存储它以提高效率。

答案 2 :(得分:5)

这是有道理的,例如,分配的块的大小可能不一定与数组的大小相同。虽然it is true new[]可以存储元素的数量(调用每个元素析构函数),但它不需要,因为空的析构函数不需要它。实现new[]存储数组长度的方法也没有标准方法(C++ FAQ Lite 1C++ FAQ Lite 2),因为每种方法都有其优缺点。

换句话说,它通过不指定任何有关实现的内容,允许尽可能快地分配。 (如果实现必须每次都存储数组的大小以及分配的块的大小,则会浪费您可能不需要的内存。)

答案 3 :(得分:3)

简单地说,C ++标准不需要支持。如果你对编译器的内部结构有足够的了解,你可以弄清楚如何访问这些信息,但这通常被认为是不好的做法。请注意,堆分配的数组和堆栈分配的数组的内存布局可能存在差异。

请记住,你在这里谈论的本质上也是C风格的数组 - 即使newdelete是C ++运算符 - 并且行为是从C继承的。如果你想要的话一个C ++“数组”,你应该使用STL(例如std :: vector,std :: deque)。