在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;
答案 0 :(得分:19)
调用delete[]
时会发生两件事:
在调用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 ++常见问题解答