代码之家  ›  专栏  ›  技术社区  ›  Peter Alexander

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

  •  19
  • Peter Alexander  · 技术社区  · 15 年前

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

    除非我错过了什么?

    4 回复  |  直到 10 年前
        1
  •  15
  •   AnT stands with Russia    15 年前

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

    实际上,在一个典型的实现中, 新的[] /删除[] 调用最终由一些特定于实现的 MALC/C -就像一对,意思是 delete[] 不必关心要释放多少内存:它只是调用内部 free (或者不管它叫什么名字),它负责处理这个问题。

    什么 删除[ ] 但需要知道有多少元素 破坏 在数组元素类型具有非平凡析构函数的情况下。这就是你的问题所在- 数组元素的数目 ,而不是块的大小(这两个不相同,块可能比数组本身实际需要的大)。因此,数组中元素的数量通常也存储在块中 new[] 后来被 删除[ ] 执行正确的数组元素销毁。也没有标准的方法来访问这个号码。

    (这意味着在一般情况下,由 新[ ] 将独立,同时存储 二者都 物理块大小(字节) 数组元素计数。这些值由不同级别的C++内存分配机制存储:原始内存分配器和 新[ ] 它们本身——并且不以任何方式相互作用)。

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

    为了说明以上内容,当您创建 int S

    int *array = new int[100];
    

    数组的大小(即 100 通常由 新[ ] 自从 删除[ ] 不在乎它( int 没有析构函数)。块的物理大小(如400字节或更多)通常由原始内存分配器存储在块中(并由调用的原始内存释放定位器使用)。 删除[ ] 但是,由于某些特定的实现原因,它很容易被证明是420。所以,这个大小对您来说基本上是无用的,因为您将无法从中获得确切的原始数组大小。

        2
  •  7
  •   Dan Olson    15 年前

    您很可能可以访问它,但是它需要您的分配器的详细知识,并且不可移植。C++标准没有指定 怎样 实现存储这些数据,因此没有一致的方法来获取它。我认为它没有指定,因为不同的分配器可能希望以不同的方式存储它,以提高效率。

        3
  •  5
  •   Yacoby    15 年前

    这是有意义的,例如,分配的块的大小不一定与数组的大小相同。同时 it is true 那个 new[] 可以存储元素数(调用每个元素析构函数),因为空析构函数不需要这样做。也没有标准的方法( C++ FAQ Lite 1 , C++ FAQ Lite 2 )在哪里实施 新[ ] 存储数组长度,因为每个方法都有其优点和缺点。

    换句话说,通过不指定任何关于实现的内容,它允许分配尽可能快速、廉价地进行。(如果每次实现都需要存储数组的大小和分配的块的大小,那么它会浪费您可能不需要的内存)。

        4
  •  3
  •   polarbear    15 年前

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

    请记住,您在这里所说的基本上也是C样式数组——尽管如此 new delete 是C++的运算符,并且行为是从C继承的。如果你想要一个C++的“数组”,那么你应该使用STL(例如:STD::vector,STD::DEQE)。