关于删除,删除[],操作员删除()等

时间:2010-09-02 09:21:48

标签: c++

  

可能重复:
  How does delete[] “know” the size of the operand array?
  ( POD )freeing memory : is delete[] equal to delete ?

据我了解,以下

class A {};
A* a = new A;
//
delete A;

将首先调用operator new()(全局的,或A提供的专用的)来分配适当的内存量,然后调用A的构造函数。当{{调用1}},首先调用A的析构函数,然后调用delete解除分配“正确的内存量”。

正如我在TC ++ PL中读到的那样,这种“适量的记忆”就是这样确定的:

  

要释放由new分配的空间,删除和删除[]必须能够确定分配的对象的大小。这意味着使用new的标准实现分配的对象将占用比静态对象稍多的空间。通常,一个单词用于保存对象的大小。

这是有道理的。但是operator delete()可以访问这个单词存储在哪里?就在新指针指向的地址之前?以便delete可以通过访问delete来获取要删除的尺寸?

你能澄清一下吗?

我认为答案可能有助于我了解a-sizeof<void*>的工作原理。我理解delete []将如何工作,new []将首先调用析构函数以获取“数组的所有对象”并释放所有这些内存......

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

感谢您的有用答案!

1 个答案:

答案 0 :(得分:3)

这完全取决于实施。

大多数运行时确实会在返回的内存((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)

你可以清楚地看到,在第一种情况下(new []'d数组),有4个字节用于表示元素的数量(0,0,0,10,它将值10组合在一起)。

在第二种情况下,这些字节被省略,我们看到与第一种情况相同的模式(12,0,47,8)。我不确切知道Visual C ++存储分配字节数的确切位置,但它证明了元素的数量确实存储在返回的指针之前(在Visual Studio 2005中)。