16

分配给动态分配数组的起始地址的指针是否真的没有数组大小的信息?所以我们必须使用另一个变量来存储它的大小,以便以后通过指针处理数组。

但是当我们释放动态分配的数组时,我们没有指定大小,而只是“释放 ptr”或“delete [] ptr”。free 或 delete 如何知道数组的大小?我们可以使用相同的方案来避免将数组的大小存储在另一个变量中吗?

谢谢!

4

4 回答 4

18

是的,这是真的。

delete知道内存块的大小,因为new向块添加了额外的信息(通常在返回给用户的区域之前),包含它的大小以及其他信息。请注意,这完全是特定于实现的,不应由您的代码使用。

所以回答你的最后一个问题:- 我们不能使用它 - 这是一个高度依赖平台和编译器的实现细节。


例如,在 K&R2 中演示的示例内存分配器中,这是放置在每个已分配块之前的“头”:

typedef long Align; /* for alignment to long boundary */

union header { /* block header */
  struct {
    union header *ptr; /* next block if on free list */
    unsigned size; /* size of this block */
  } s;

  Align x; /* force alignment of blocks */
};

typedef union header Header;

size是分配块的大小(然后由free, 或使用delete)。

于 2010-01-09T18:38:07.823 回答
7

有趣的是,从历史上看,delete [20] arr;它就是这样arr = new int[20]。然而实践证明,分配器可以轻松存储有关大小的信息,并且由于大多数使用它的人无论如何都会存储它,因此它被添加到标准中。

更有趣且鲜为人知的是,这种“扩展删除语法”实际上得到了一些 C++ 编译器的支持(尽管即使面对 C++98 标准也不正确),尽管没有人需要它。

int* arr = new int[20];
delete [20] arr;

然而,关于这一切的可悲之处在于,没有符合标准的方法来检索传递的大小以供您自己使用:-/

于 2010-01-09T18:45:05.803 回答
3

数组确实不包含数组的大小,您必须存储该信息以备后用。删除数组时deletefree它是指向您传递的已分配内存的指针。使用的内存管理器(由系统或您自己的自定义覆盖 new 和 delete)知道已释放的内存区域并跟踪它。希望这是有道理的。

于 2010-01-09T18:40:30.080 回答
2

对,是真的。这就是为什么你应该很少尝试直接处理这个问题的部分原因,而是使用标准容器。大约只有在您决定自己实现一个容器时才有意义处理它(在这种情况下,您通常会在容器的实现中跟踪大小信息)。

于 2010-01-09T18:42:18.843 回答