在C ++中,调用delete运算符时会发生什么?

时间:2010-08-11 01:02:57

标签: c++ arrays memory delete-operator

在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;

3 个答案:

答案 0 :(得分:19)

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

  1. 如果数组的类型具有非平凡的析构函数,则会以相反的顺序为数组中的每个元素调用析构函数
  2. 释放阵列占用的内存
  3. 在调用delete之后访问数组占用的内存会导致未定义的行为(即,可能发生任何事情 - 数据可能仍然存在,或者当您尝试读取时,程序可能会崩溃,或者可能会发生更糟糕的事情。)

答案 1 :(得分:1)

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

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

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

答案 2 :(得分: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[] nums会通过查看第一个3对象之前的固定偏移量(即int之前)来找到*num,并且会在开始时释放内存。分配(即,在*nums之前开始固定偏移的内存块。)

两种技术都不完美。以下是一些权衡。

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

分配技术更快但更危险:如果有人说delete nums他们应该说delete[] nums,那么传递给运营商delete(void* nums)的地址将不是有效的堆分配-it在有效堆分配后至少为sizeof(size_t)个字节。这可能会破坏堆。 - C ++常见问题解答