关于delete、delete[]、operatordelete()等[重复]

2023-12-30

可能的重复:
delete[] 如何“知道”操作数数组的大小? https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array
(POD)释放内存:delete[]等于delete吗? https://stackoverflow.com/questions/1553382/pod-freeing-memory-is-delete-equal-to-delete

据我了解,以下

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

将首先调用operator new()(全局的,或者 A 提供的专用的)分配适量的内存,然后调用 A 的构造函数。delete被调用时,会先调用A的析构函数,然后调用operator delete()释放“适量的内存”。

正如我在 TC++PL 中读到的,这个“适当的内存量”是这样确定的:

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

这是有道理的。但是这个词存储在哪里以便可以被访问delete?就在新指针指向的地址之前?以便delete可以通过访问获取要删除的大小a-sizeof<void*> ?

你能澄清一下吗?

我认为这个问题的答案可能会帮助我理解如何delete []作品。我明白如何new []会起作用,并且delete []将首先调用“数组的所有对象”的析构函数并释放所有这些内存......

但怎样才能delete []知道数组的大小吗?

感谢您的帮助!


这一切都取决于实施。

大多数运行时确实会在返回的内存之前存储内存大小((BYTE *)p-sizeof(size_t))但还有其他选择。在我自己的内存管理器中(是的,我写了这种东西),在返回的内存之前我有一个更复杂的数据结构(使用指向链表、校验和...的指针)。实际上由内存管理器决定在哪里存储这些信息。

除了分配的内存大小之外,new[] 还将存储实例的数量,以便它知道要调用多少个析构函数。这通常超出了内存管理器的范围,并且通常由 C++ 运行时/编译器本身处理。但同样,实例数量的存储位置取决于编译器,尽管实际上我希望将其存储在返回的内存之前(以及内存管理器存储的任何数据之后)。

EDIT:下面的小实用程序显示了分配内存之前的内存布局:

#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 中)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于delete、delete[]、operatordelete()等[重复] 的相关文章

随机推荐