C++-关于类对象的delete 与delete[]内存泄露问题
class MyClass
{
public:
char x;
MyClass():x(1)
{
};
};
int main(int argc,char** argv)
{
while(1)
{
MyClass *a=new MyClass[10];
delete a;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我想问一下LZ,你怎么知道没有产生内存泄露。少量内存泄露一般不会引起系统崩溃。所以不是为什么不会产生内存泄露。是产生了而你还没注意到。
一般用自定义类型的定义数组是你定义的数组有多大。你就需要构造几次。而同样配合使用的是delete[];因为delete[]是定义的数组多大。就会有几次析构。而你是用的是delete他只会使
数组中的第0号对象析构掉。只有这段内存重新交还给系统管理。其他的内存你也不能访问。系统也管理不到。这就是所谓的内存泄露
内存泄露,C++通常是指new出来的内存没有delete掉。在你的代码里边,new了一块内存,然后马上就delete,自然就没有内存泄露了(呃……其实我也不确定啦,因为你用的是delete,而不是delete[])。
而在评论里面说的,把x换成指针,在构造函数里new一块内存给它,10秒钟内系统就要卡死。如果没有在析构函数里面delete,自然,就会发生上一段所说的,new出来的内存没有delete掉,内存泄露啰!系统也就由此卡死。
那么x换成指针类型后,析构函数里面也用了delete,是不是就不会发生内存泄露呢?不是的。因为“new MyClass[10]”的时候,MyClass的构造函数调用了10次,而“delete a”的时候,MyClass的析构函数只被调用了1次!因为使用delete,就是告诉编译器,a所指的地方,只有一个MyClass对象!
那有什么办法告诉编译器,a所指是一个MyClass数组,而不是单个对象呢?使用 delete[]。那样,编译器就会知道,a所指的地方,有10个MyClass对象(至于怎么知道的,不在这里讨论),于是针对每个对象调用一次析构函数。也就不会有内存泄露了。
记得用delete配对new,用delete[]配对new[]。事实上,代码里边用delete来配对new[],行为未定义,嗯,是C++标准里面没有定义。也许是因为你比较幸运,程序没有表现出问题~~
补充回答一下楼主的疑问:为什么“使用delete删除基础数据类型的数组也是不会发生泄漏的”?
看下面的代码:
char *c = new char[10];
delete c;
在“delete c;”时,我们可以认为程序执行了以下两个动作:
1. 针对被delete对象的类型,调用相应的析构函数。因为这里是基础数据类型char,所以没有任何实质性动作。
2. 回收指针c所指的内存块。这里,c的类型没有起作用。就是说,系统并不会因为c的类型是char而只回收一个字节。系统所做的是,根据c的值,找到对应的内存块的大小,以及其他相关信息,然后回收。这些信息哪里来?调用new、new[]的时候记录下来的。记录在什么地方?这是new、new[]的实现者,或者更底层程序的实现者所要关心的......
需要再次强调的是,楼主没有看到内存泄露的现象,并不表示“使用delete删除基础数据类型的数组”是安全的!
这里要说下delete和delete []的一个区别。
如果你用new分配一个对象数据,如:
MyClass *a=new MyClass[10];
delete a和delete []a的区别在于,后者要调用10次析构函数后再释放空间(通常是调用free()系实现),而前者只会调用a[0]的析构函数后再释放空间。
因此,对于在堆上给a分配的空间,不管是delete a还是delete []a都会正常释放掉,但它们的区别在于,delete a不会调用a[1]--a[9]的析构函数。所以你的代码不会出现内存泄露。
但是我们看看下面的程序代码:
class MyClass
{
public:
char x;
int* pa;
MyClass():x(1)
{
pa = new int[1000];
};
~MyClass()
{
delete []pa;
}
};
int main(int argc,char** argv)
{
while(1)
{
MyClass *a=new MyClass[10];
delete a;
}
}
在这段程序里,因为析构函数负责对pa的释放,若没有调用,程序将出现重大的内存泄露
内存泄露是设计bug,可能不会展现编译运行错误。
windows平台VC、VS下使用_CrtDumpMemoryLeaks()去检测内存泄露吧。