【发布时间】:2011-01-03 07:35:03
【问题描述】:
分配给动态分配数组起始地址的指针是不是没有数组大小的信息?所以我们必须使用另一个变量来存储它的大小,以便以后通过指针处理数组。
但是当我们释放动态分配的数组时,我们没有指定大小,而只是“释放 ptr”或“delete [] ptr”。 free 或 delete 如何知道数组的大小?我们可以使用相同的方案来避免将数组的大小存储在另一个变量中吗?
谢谢!
【问题讨论】:
标签: c++ c dynamic-allocation
分配给动态分配数组起始地址的指针是不是没有数组大小的信息?所以我们必须使用另一个变量来存储它的大小,以便以后通过指针处理数组。
但是当我们释放动态分配的数组时,我们没有指定大小,而只是“释放 ptr”或“delete [] ptr”。 free 或 delete 如何知道数组的大小?我们可以使用相同的方案来避免将数组的大小存储在另一个变量中吗?
谢谢!
【问题讨论】:
标签: c++ c dynamic-allocation
是的,这是真的。
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 使用)。
【讨论】:
n 传递给 new T[n] somewhere 以便它可以在调用delete[] 时调用析构函数n 次。当然,它存储n 的方式和位置与存储原始块大小的实现一样。
数组确实不包含数组的大小,您必须存储该信息以备后用。通过delete 或free 删除数组时,它是指向您传递的已分配内存的指针。使用的内存管理器(由系统或您自己的自定义覆盖 new 和 delete)知道已释放的内存区域并跟踪它。希望有道理。
【讨论】:
是的,这是真的。这就是为什么你应该很少尝试直接处理这个问题的部分原因,而是使用标准容器。唯一有意义的处理是如果您决定自己实现一个容器(在这种情况下,您通常会在容器的实现中跟踪大小信息)。
【讨论】:
有趣的是,历史上它是delete [20] arr;,就像它是arr = new int[20]。然而实践证明,分配器可以轻松存储有关大小的信息,并且由于大多数使用它的人无论如何都会存储它,因此它被添加到标准中。
更有趣且鲜为人知的是,这种“扩展删除语法”实际上得到了一些 C++ 编译器的支持(尽管即使在 C++98 标准面前也不正确),尽管没有一个需要它。
int* arr = new int[20];
delete [20] arr;
然而,关于这一切的可悲之处在于,没有符合标准的方法来检索传递的大小以供您自己使用:-/
【讨论】: