2

在 C++ 中,我理解delete操作符在与数组一起使用时会“破坏”它,释放它使用的内存。但是当这完成时会发生什么?

我想我的程序只会标记堆的相关部分被释放以供重用,然后继续。

但我也注意到,数组的第一个元素设置为 null,而其他元素保持不变。这是为了什么目的?

int * nums = new int[3];
nums[0] = 1;
nums[1] = 2;

cout << "nums[0]: " << *nums << endl;
cout << "nums[1]: " << *(nums+1) << endl;

delete [] nums;

cout << "nums[0]: " << *nums << endl;
cout << "nums[1]: " << *(nums+1) << endl;
4

3 回答 3

19

调用时会发生两件事delete[]

  1. 如果数组是具有非平凡析构函数的类型,则以相反的顺序为数组中的每个元素调用析构函数
  2. 数组占用的内存被释放

在调用后访问数组占用的内存会delete导致未定义的行为(也就是说,任何事情都可能发生——数据可能仍然存在,或者当您尝试读取它时您的程序可能会崩溃,或者可能发生其他更糟糕的事情)。

于 2010-08-11T01:05:20.850 回答
1

它为 NULL 的原因取决于堆实现。

一些可能的原因是它正在使用空间进行自由空间跟踪。它可能将其用作指向下一个空闲块的指针。它可能正在使用它来记录空闲块的大小。它可能正在写入一些序列号以进行新/删除调试跟踪。

它可能只是写 NULL,因为它感觉像它。

于 2010-08-11T01:19:58.090 回答
0

每当有人说int* nums = new int[3],运行时系统需要将对象的数量存储3在一个只知道指针就可以检索的地方nums。编译器可以使用它想使用的任何技术,但有两种流行的技术。

生成的代码nums = new int[3]可能会将数字存储3在静态关联数组中,其中指针nums用作查找键,数字3是关联值。生成的代码delete[] nums将在关联数组中查找指针,提取关联的 size_t,然后从关联数组中删除条目。

生成的代码nums = new int[3]可能会分配额外的 sizeof(size_t) 字节内存(可能加上一些对齐字节)并将值放在3第一个int对象之前。然后delete[] nums3通过查看第一个int对象之前的固定偏移量(即 before *num)来找到,并从分配开始处开始释放内存(即,从固定偏移量 before 开始的内存块*nums)。

两种技术都不是完美的。这里有一些权衡。

关联数组技术更慢但更安全:如果有人[]在解除分配数组时忘记了,(a)关联数组中的条目将是泄漏,并且(b)只有数组中的第一个对象会被破坏。这可能是也可能不是一个严重的问题,但至少它可能不会使应用程序崩溃。

过度分配技术更快但更危险:如果有人说delete nums他们应该说的地方delete[] nums,传递给 operator 的地址delete(void* nums)将不是有效的堆分配——它至少sizeof(size_t)是有效堆分配之后的字节。这可能会破坏堆。- C++ 常见问题

于 2010-08-11T02:24:21.923 回答