delete 和 delete[]的区别
从直观角度看,delete就是释放单个ptr对象指向的内存,delete[]释放连续多个ptr对象指向的内存;
释放单个对象内存:
string* a = new string;
delete string;
释放连续内存:
int* string = new string[10];
for (int i = 0; i < 10; i++)
{
*(a + i) = "1";
}
delete[] a;
释放连续内存的特例:
int* a = new int[10];
for (int i = 0; i < 10; i++)
{
*(a + i) = i;
}
delete a;
//delete a[];
这段代码中的int* a指向连续的int空间,但是析构用delete也可以释放,不是应该用delete[]吗?
原因:
当连续内存空间存放简单类型时,如:int char double 和 某些无析构函数的自定义类型…,其内存大小已经确定,系统可以记忆并且进行管理,在delete他们时,系统并不会调用析构函数而是直接标记未使用状态;
除了上面这种特例外,释放连续非简单类型对象(string 自定义类型等有析构函数的类型),必须使用delete[],其对象内存大小可变,需要调用其中的析构函数依次彻底释放,否则会造成内存泄漏;
错误代码:
string *a = new string[10];
for (int i = 0; i < 10; i++)
{
*(a + i) = "1";
}
delete a;//此处应该使用delete[] a;
原因:
string是非简单类型,delete a; 仅释放了a[0]对象的内存,并未释放a[1]~a[9]导致内存泄露 ;因此释放非简单类型的时候需要用delete[];
-
因为非简单类型释放的时候,会去0位置上一个拿到一个int,代表对象个数,通过这个个数,不断的调用delete答到完全释放,防止内存泄漏delete[]能做到连续释放自定义类型的原因是,释放位置前一个地址能拿到这个连续对象的size(),这样就能连续释放了!
-
如图,这个0x0096126C是b的地址; 他的前一个地址存了这个b有多少连续的对象;
-
总结
- 释放简单类型时delete不管是释放单个对象内存还是连续对象内存都可以完成;
- 释放非简单类型delete只能释放单个对象内存,若new[n]开辟了连续多个内存,只能使用delete[]释放,否则会造成内存泄漏;
- 为了规范使用,在new一个对象内存的情况下我们使用delete,在new[n]多个对象内存的情况下我们使用delete[],这样就不会用错;