这一切都取决于实施。
大多数运行时间确实会在返回的内存之前存储内存大小((BYTE *)p-sizeof(size_t)
),但还有其他选择。在我自己的内存管理器中(是的,我写这种东西),在返回的内存之前,我有一个更复杂的数据结构(使用指向链接列表的指针,校验和......)。实际上由内存管理员决定在哪里存储这些信息。
除了分配内存的大小之外,new []还会存储实例的数量,以便知道要调用多少个析构函数。这通常超出了内存管理器的范围,通常由C++运行时/编译器本身处理。但是,这个实例的存储位置取决于编译器,尽管在实践中我会希望将其存储在返回的内存之前(以及内存管理器存储的任何数据之后)。
编辑: 下面的小工具,显示了分配的内存之前,内存布局:
#include <iostream>
typedef unsigned char Byte;
class X
{
public:
X() : m_value(1) {}
~X() {m_value = 0;}
private:
int m_value;
};
void print(Byte *p,int offset)
{
printf ("Value at %d: 0x%x (%d)\n", offset, p[offset], p[offset]);
}
void main()
{
X *x = new X[10];
std::cout << "Address of x: " << x << std::endl;
std::cout << "sizeof(X) : " << sizeof(X) << std::endl;
Byte *p = (Byte *)x;
print(p,-1);
print(p,-2);
print(p,-3);
print(p,-4);
print(p,-5);
print(p,-6);
print(p,-7);
print(p,-8);
print(p,-9);
print(p,-10);
X *y = new X;
std::cout << "Address of y: " << y << std::endl;
p = (Byte *)y;
print(p,-1);
print(p,-2);
print(p,-3);
print(p,-4);
print(p,-5);
print(p,-6);
print(p,-7);
print(p,-8);
print(p,-9);
print(p,-10);
}
运行此给出以下输出(在Visual Studio 2005中):
Address of x: 00481DE4
sizeof(X) : 4
Value at -1: 0x0 (0)
Value at -2: 0x0 (0)
Value at -3: 0x0 (0)
Value at -4: 0xa (10)
Value at -5: 0xc (12)
Value at -6: 0x0 (0)
Value at -7: 0x2f (47)
Value at -8: 0x8 (8)
Value at -9: 0x2f (47)
Value at -10: 0x98 (152)
Address of y: 00481E70
Value at -1: 0xc (12)
Value at -2: 0x0 (0)
Value at -3: 0x2f (47)
Value at -4: 0x8 (8)
Value at -5: 0x2a (42)
Value at -6: 0x98 (152)
Value at -7: 0xf8 (248)
Value at -8: 0xb0 (176)
Value at -9: 0x0 (0)
Value at -10: 0x48 (72)
你可以清楚地看到,在第一种情况下(新的[]'d数组),有4个字节用于表示元素的数量(0,0,0,10,这使得数值10)。
在第二种情况下,这些字节被省略,我们看到与第一种情况相同的模式(12,0,47,8)。我不清楚Visual C++在哪里存储分配的字节数,但它证明了元素的数量确实存储在返回的指针之前(在Visual Studio 2005中)。
我认为这是依赖于实现的,但更多的启发性的人肯定会更具体。 – ereOn 2010-09-02 09:26:57
无主复制,对不起。 – 2010-09-02 09:38:13
相关:[(POD)释放内存:是删除\ [\]等于删除?](http://stackoverflow.com/questions/1553382/pod-freeing-memory-is-delete-equal-to-delete) – sbi 2010-09-02 09:55:04