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

问题描述:

可能重复:
How does the standard new operator work in c++?
How does delete[] “know” the size of the operand array?delete []如何知道数组的大小?

How does delete[] "know" the size of the operand array?

杜佩我很好奇如何走出分配内存的大小删除[]的数字。当我做这样的事情时:

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

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

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

我可以免费获得5或9号的表吗?我对新[]和删除[]共享关于它们的大小的信息感兴趣。或者我可能在这里缺少一些重要的东西。

+0

重复(或多或少)http://*.com/questions/377178/how-does-the-standard-new-operator-work-in-c/377208 – 2009-06-10 14:06:18

+3

我不同意,这是更具体。 – 2009-06-10 14:11:31

+0

作为一个方面的说明,正如答案中所述,这是实现特定的东西。 这意味着您不应该依赖于提取数组大小的方式,因为它可能会从编译器转换为编译器,从编译器版本转换为编译器版本。 – 2009-06-10 14:13:40

它会删除一个大小为9的数组。 它删除指针指向的数组。

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

int* table = new int[5]; 

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

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

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

中的C++ 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. 

我的猜测是,新的[]实际上分配更多的数据似乎比。在返回指针指示数组中有多少项之前,它可能有几个字节。

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

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

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

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

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

你可以想像,系统存储的表中的结构大小是这样的:

struct MemoryAllocated 
    { 
    size_t sizeOfMemory; 
    char* yourData; 
    } 

每键入您分配一些内存,系统会返回一个指向“yourData”。 并且每种类型的内存都是“空闲”的,系统会移动指针以获取“sizeOfMemory”。请参见std :: allocator

在新的[]/delete []情况下,会发生什么情况与在新/删除情况下发生的情况相同/类似...大小信息存储在)分配块本身。数组有趣的地方在于它还使用大小信息来知道调用析构函数的对象数量。