目录
区别
简单来说:delete p会调用一次析构函数,而delete[] p会调用每个成员的析构函数。
class A {
public:
~A() { cout << "A的析构函数" << endl; }
};
int main()
{
A* pA = new A[10];
delete[]pA;//输出10次A的析构函数
//delete pA;//会出错,因为只析构了一次
A* pA1 = new A;
delete pA1;//输出一次A的析构函数
//delete[] pA1;//编译器不会报错,但是系统会一直调用析构函数
int* pInt = new int[10];
delete[] pInt;
//delete pInt;//不会出错
int* pInt1 = new int;
delete pInt1;
//delete[] pInt1;//不会出错
return 0;
}
由上面的代码可以看出,delete[] p和delete p的区别在于他们对于非内部数据对象处理上。
如果数组类型是自定义类,那么new[]只能用delete[]来对应,new和delete对应;
但是对于普通数据类型而言,他们作用的效果是一样的,例如int* p=new int[10],delete p和delete[] p作用效果是一样的,原因是内部普通数据类型没有析构函数。
这边针对“普通数据类型delete和delete[]效果一样”再做另一个例子说明:
int *p = new int[10];
int a = 102;
int *q = &a;
std::list<int *> m_listInt;
for (int i = 0; i< 10; i++)
{
*(p+i) = i + 100;
m_listInt.push_back(p+i);
}
//正常释放
for (auto it = m_listInt.begin(); it != m_listInt.end(); )
{
it = m_listInt.erase(it);
}
m_listInt.clear();
delete[] p;
//代码段二
for (auto it = m_listInt.begin(); it != m_listInt.end(); )
{
int *qq;
qq = *it;
it = m_listInt.erase(it);
delete qq; //本意是想逐个元素提取出来后删除,但是执行完此句后,内存都全部释放了
}
m_listInt.clear();
原先我是想用代码段二,将元素逐个从list内提取移除后,释放数据本身内存,但是执行了delete qq后,list队列内的其他数据内存也被释放了。这就是对于普通数据而言,delete和delete[]实现的效果是一样的。
所以会有这样一个题目:
char *p = new char[100];
delete p;
这样会有什么问题?
实际上正确的回答是:不会有内存泄漏,但是不建议这样使用。
延伸
这边简单说一下new、delete和malloc、free的区别
①malloc/free是c中的库函数,用来动态申请/释放内存空间;
②new/delete是c++中的关键字,需要编译器支持,允许重载,new会调用构造函数、delete会调用析构函数;
③new 不用指定内存块大小,会根据类型信息自己申请,malloc则需要显式指出所需内存的大小;
④new返回类型为指针,类型严格与对象匹配,而malloc成功返回void*,需要强制类型转换为我们需要的类型;
⑤new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL;
⑥new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。
注意:
此处我个人认为,自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区,可以位于堆之上也可以通过重载位于全局存储区(偏逻辑概念)。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配(偏物理概念)。
如有不对,请指正。
相关参考链接:参考链接