C++ 为什么运算符new[]为数组大小分配内存?
我实现了一个堆栈分配器,并为某个类重载了C++ 为什么运算符new[]为数组大小分配内存?,c++,dynamic-memory-allocation,C++,Dynamic Memory Allocation,我实现了一个堆栈分配器,并为某个类重载了操作符new[],以使用我自己的分配器。然后我注意到操作符new[]为分配的数组中的元素数量分配了内存。 例如: test_class*test_arr=新的测试类[5] 从我的分配器请求8个字节+5*sizeof(test_类),并在前8个字节中存储数组的大小,在本例中为5 为什么会这样?我的分配器的工作是跟踪分配的内存量。对于那部分来说,这真的没有意义,是吗?那有什么意义呢? 另外,我是否可以(或不应该?)以某种方式“关闭它”?很可能newt[N]将请
操作符new[]
,以使用我自己的分配器。然后我注意到操作符new[]
为分配的数组中的元素数量分配了内存。例如:
test_class*test_arr=新的测试类[5]代码>
从我的分配器请求8个字节+5*sizeof(test_类),并在前8个字节中存储数组的大小,在本例中为5
为什么会这样?我的分配器的工作是跟踪分配的内存量。对于那部分来说,这真的没有意义,是吗?那有什么意义呢?
另外,我是否可以(或不应该?)以某种方式“关闭它”?很可能newt[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
传递给要释放的底层分配器。当您在代码中写入p=new t[N]
时,编译器生成调用运算符new[]
为T
类型的N
对象以及它需要的任何簿记信息分配足够的内存。当您随后调用delete[]p
时,编译器为p
指向的数组中的每个N
元素调用析构函数,然后调用操作符delete[]
释放从operator new[]获取的内存。
但是N
并不总是具有相同的值。您可以执行p=new t[3];delete[]p;p=new t[4];delete[]p;
,这两次删除将分别运行不同数量的析构函数
为了调用正确数量的析构函数,必须在某个地方有一个注释,记录p
指向的数组中有多少个对象。该注释通常存储在编译器通过调用操作符new[]
获得的内存的簿记部分。这就是为什么它需要额外的空间
这是当今的典型实现,但编译器不需要这样做。例如,至少有一个早期实现保留了指针值和析构函数计数的单独表
此外,许多实现不会对没有析构函数的类型使用额外的开销。因此int*p=new int[3]
只需调用operator new(3*sizeof(int)
,而delete[]p
只需调用operator delete(p)
分配器通过存储大小和分配的内存来跟踪分配的内存。查看操作员删除[]的代码
@MustafaOzturk In libstdc++delete
只将void*
传递给std::free
。因此在我的示例中,它将传递指向第一个test\u类
元素的指针。free
不知道指针的类型,那么为什么数组中的元素数量会带来好处呢?我不是专家但是,如果你的类有一个不重要的析构函数,DEL[]需要知道它在C++上的调用元素有多少个[D][/C]>不<代码>删除< /C>。
存储数组中对象的数量,以便操作符delete[]
知道必须销毁多少对象。似乎是这样,但这是标准指定的吗?同时void*
会传递给delete[]
,delete如何知道调用哪个类析构函数?@MikevanDyke:当析构函数传递到delete[]时,它已经被调用了。
。小心伪指针算法:*(p-sizeof(size\t))
没有意义,除非p
具有类型char*
。对于任何其他指针类型p-sizeof(size\t)
指向杂草,并且行为未定义。您可以执行(size\t*)p-1
而不是。@jxh——也许吧。我的观点更多的是建议讨论它是如何工作的,而不是试图拼凑一段代码片段,它可能会或可能不会显示实际发生了什么。