delete []如何知道数组的大小?

时间:2009-06-10 14:00:52

标签: c++

我很好奇delete []如何计算分配内存的大小。当我做类似的事情时:

int* table = new int[5];
delete[] table;

我明白表的内存已被释放。但是,如果我将指针重新分配给某个不同的表,会发生什么。

int* table = new [5];
int* table2 = new [9];
table = table2;
delete[] table;

我可以免费获得5或9大小的桌子吗?我对new []和delete []如何共享有关其大小的信息感兴趣。或者也许我错过了一些必要的东西。

8 个答案:

答案 0 :(得分:16)

C ++ FAQ lite的

Section 16.14回答了这个问题:

  

有两种流行的技巧   做这个。这两种技术都在   由商业级编译器使用,   两者都有权衡,也没有   完善。这些技巧是:

* Over-allocate the array and put n just to the left 
  of the first Fred object.
* Use an associative array with p as the key and n as the value.

答案 1 :(得分:12)

它将删除大小为9的数组。 它删除指针指向的数组。

未指定如何存储大小信息,因此每个编译器可以以不同的方式实现它,但是常见的方法是在数组之前分配额外的块。也就是说,当你这样做时:

int* table = new int[5];

它实际上分配了一个包含6个整数的数组,并将数组大小存储在第一个元素中。然后它返回指向第二个元素的指针。所以要找到大小,删除[]只需要读表[-1],基本上。

这是一种常见的方法,但语言标准并没有指定必须以这种方式完成。只是它必须工作

另一种方法可能是将数组的地址用作某个全局哈希表的键。任何方法都有效,只要它产生正确的结果。

答案 2 :(得分:4)

如何完成这项工作是特定于编译器的细节。但是,假设没有内存损坏,删除[]的调用将始终删除正确数量的元素。有几种方法可以实现这一点,但一种简单的方法是隐藏内存中的长度。

这是一个很好而简单的方法来实现它以用于演示目的。假设您的代码调用new int [10]。编译器不分配10 * sizeof(int),而是分配(10 * sizefo(int))+ sizeof(size_t)。然后它返回一个指向你的指针,它从头开始偏移size_t。在初始size_t空间内,它写入数字10.现在当你调用delete []并传入一个指针时,编译器只是向后移动size_t字节并找到要删除的元素数。

答案 3 :(得分:2)

delete []的工作原理是依赖于实现的,但是全局new运算符以某种方式将描述符与分配的内存相关联(在大多数情况下,它预先分配给分配的内存,或存储在查找表中)。描述符包含已分配的内存的实际大小。

在你的第二个代码示例中,delete []将正确删除int的九元素数组,并且原始的五元素数组将被泄露。

答案 4 :(得分:1)

该机制依赖于实现,但是通过重新分配示例中的指针,它不会被“欺骗”。它将释放大小为9的数组,就像你告诉它的那样(在这种情况下会出现内存泄漏,因为大小为5的数组现在没有指向它)。

答案 5 :(得分:0)

我的猜测是new []实际上分配的数据比看起来多。它可能在返回的指针之前有几个字节,它告诉数组中有多少项。

答案 6 :(得分:0)

你可以想象系统将表的大小存储在如下结构中:

struct MemoryAllocated
  {
  size_t sizeOfMemory;
  char* yourData;
  }

每种类型分配一些内存,系统返回一个指向'yourData'的指针。 每种类型的内存都是“空闲的”,系统会将指针移动到'sizeOfMemory'。另请参见std :: allocator

答案 7 :(得分:0)

在new [] / delete []的情况下,内存方式与新/删除情况相同/相似...大小信息存储在(较大的)已分配块本身内。数组的有趣之处在于它还使用大小信息来知道调用析构函数的对象数量。