为什么operator new []为数组的大小分配内存?

时间:2018-04-27 19:40:15

标签: c++ dynamic-memory-allocation

我正在实现一个堆栈分配器并为某个类重载operator new[]以使用我自己的分配器。然后我注意到operator new[]为分配的数组中的元素数量分配了内存 例如:

test_class* test_arr = new test_class[5];

从我的分配器请求8个字节+5 * sizeof(test_class),在前8个字节中它存储数组的大小,在这种情况下为5。

为什么这样做?我的分配器的工作是跟踪分配的内存量。对于那部分它真的没有意义,是吗?那有什么意义呢? 此外,我可以(或不应该吗?)我以某种方式“关闭”?

2 个答案:

答案 0 :(得分:2)

最有可能new T[N]将请求指针p到大小为sizeof(size_t) + N * sizeof(T)字节的内存,将N存储在第一个sizeof(size_t)字节中,然后返回(T*)(((size_t*)p)+1)用户(因此第一个T位于返回的指针处。)

然后delete[]将获取给定的指针,查看*(p-sizeof(size_t))以查看要销毁的对象数量,销毁它们,并将((size_t*)p)-1传递给要释放的基础分配器。

答案 1 :(得分:1)

当您在代码中编写p = new T[N]时,编译器会生成调用operator new[]的代码,以便为类型为N的{​​{1}}对象分配足够的内存,以及所需的任何簿记信息。当您随后调用T时,编译器为delete[] p指向的数组中的每个N元素调用析构函数,然后调用p以释放它所获得的内存来自operator delete[]

operator new[]并不总是具有相同的价值。你可以做N,两次删除会分别运行不同数量的析构函数。

为了调用正确数量的析构函数,必须在某处记录p = new T[3]; delete[] p; p = new T[4]; delete[] p;指向的数组中有多少个对象。该注释通常存储在编译器从调用p获得的内存的簿记部分中。这就是它需要额外空间的原因。

这是目前的典型实现,但编译器并不需要这样做。例如,至少有一个早期实现保留了一个指针值和析构函数计数的单独表。

此外,许多实现不会为没有析构函数的类型使用额外的开销。因此operator new[]只需拨打int *p = new int[3]operator new(3*sizeof(int)只需拨打delete[] p