c++中什么时候用new[]申请,可以用delete释放
2017-11-08 19:01
726 查看
首先想到的是c语言中的 malloc 和 free ,这两个是库函数,而在c++中 new 和 delete是运算符(和 + - * /一样),在使用new的时可以看成使用默认使用构造函数+malloc,使用delete时可以看成使用析构函数+free。
简单说一下malloc
系统管理堆内存运用的是链表的方式:分配堆内存地址时依次由低向高遍历”堆链“,但遇到大小合适的堆块时,将这个堆块从”堆链“中删除,其他的继续构成新的链。当这一块的内存分配完后还有剩余,则将剩余的继续添加到”堆链“里。
分配空间时,不仅会分配到程序员所需空间的大小,系统还会分配一个头”Header“
可以说这个Header中保存了一个所申请空间的大小,而系统返回的Header是不能被用户访问的。
接下来是正文
情况1
第一种方式一定会造成内存泄漏吗?
其实两种释放内存的方式效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数。
(它直接通过指针可以获取实际分配的内存空间,在分配过程中系统会记录分配内存的大小等信息,此信息保存在结构体CrtMemBlockHeader中,具体情况可参看VC安装目录下CRT/SRC/DBGDEL.cpp)
情况2
如果是类class,则情况会出现不同
这个程序运行后会出现这个错误
这个错误的意思是程序在结束后系统会调用析构函数发现我们在上面malloc中提出的Header被错误的更改了。
假设用户接受到的指针返回值是address,因为在使用delete[]时,会默认从address-4开始,而不是addrss。(4是因为malloc结构体中的类型为long,而且在32位系统下。这里减一是一个单元格,也就4)。而这个结构体中存储的size是将要释放的大小。
这个是加上那个引用后的运行结果,可以看到它只析构了一次。
所以1. delete a 仅释放了a指针指向的全部内存空间,但是只调用了a[0]的析构函数,剩下的a[1]和a[2]中m申请的内存不能够释放,则造成了内存泄漏。
2. delete[] a 释放了a指针申请的内存并且调用析构函数释放掉所有申请的内存
总结一下:假设 ptr 代表new返回的内存空间地址
delete ptr 代表释放ptr指向内存,并且只能用来释放内存。
delete[] ptr 代表释放ptr指向的内存,并且逐个调用对象的析构函数。
对于像int/char/long/int*/struct等简单数据类型,由于没有析构函数,所以delete和delete[] 是一样!但是c++中的对象数组就不同了!
如果对象中使用了外部的资源(或操作系统资源)例如:socket,file,thread等,这些资源都是有限的,端口号最大是65535,如果不被释放,在没有端口可以用的时候,连网都上不去!
所以,在生成对象数组时,一定要记得用delete[]!
简单说一下malloc
系统管理堆内存运用的是链表的方式:分配堆内存地址时依次由低向高遍历”堆链“,但遇到大小合适的堆块时,将这个堆块从”堆链“中删除,其他的继续构成新的链。当这一块的内存分配完后还有剩余,则将剩余的继续添加到”堆链“里。
分配空间时,不仅会分配到程序员所需空间的大小,系统还会分配一个头”Header“
typedef long Align;/*按照long类型的边界对齐*/ union header/*块的头部*/ { struct { union header *ptr;/*空闲块链表中的下一块*/ unsigned size;/*本块的大小*/ }s; Align x;/*强制块对齐* };
可以说这个Header中保存了一个所申请空间的大小,而系统返回的Header是不能被用户访问的。
接下来是正文
情况1
int* a = new int[10]; delete a; delete[] a;
第一种方式一定会造成内存泄漏吗?
其实两种释放内存的方式效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数。
(它直接通过指针可以获取实际分配的内存空间,在分配过程中系统会记录分配内存的大小等信息,此信息保存在结构体CrtMemBlockHeader中,具体情况可参看VC安装目录下CRT/SRC/DBGDEL.cpp)
情况2
如果是类class,则情况会出现不同
class A { public: A() { m = new int[10]; } ~A() { cout<<"~A"<<endl; } private: char* m; }; int main() { A* ptr = new A[3]; //ptr = ptr - 1;//注1 delete ptr; return 0; }
这个程序运行后会出现这个错误
这个错误的意思是程序在结束后系统会调用析构函数发现我们在上面malloc中提出的Header被错误的更改了。
假设用户接受到的指针返回值是address,因为在使用delete[]时,会默认从address-4开始,而不是addrss。(4是因为malloc结构体中的类型为long,而且在32位系统下。这里减一是一个单元格,也就4)。而这个结构体中存储的size是将要释放的大小。
这个是加上那个引用后的运行结果,可以看到它只析构了一次。
所以1. delete a 仅释放了a指针指向的全部内存空间,但是只调用了a[0]的析构函数,剩下的a[1]和a[2]中m申请的内存不能够释放,则造成了内存泄漏。
2. delete[] a 释放了a指针申请的内存并且调用析构函数释放掉所有申请的内存
总结一下:假设 ptr 代表new返回的内存空间地址
delete ptr 代表释放ptr指向内存,并且只能用来释放内存。
delete[] ptr 代表释放ptr指向的内存,并且逐个调用对象的析构函数。
对于像int/char/long/int*/struct等简单数据类型,由于没有析构函数,所以delete和delete[] 是一样!但是c++中的对象数组就不同了!
如果对象中使用了外部的资源(或操作系统资源)例如:socket,file,thread等,这些资源都是有限的,端口号最大是65535,如果不被释放,在没有端口可以用的时候,连网都上不去!
所以,在生成对象数组时,一定要记得用delete[]!
相关文章推荐
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- C++在堆上申请和释放内存 - new & delete
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- C++中new申请的内存, 可以用free释放吗?
- malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存
- c++基础之用new和delete申请内存与创建对象
- C++的指针的坑:“new[]的指针需要delete[]”和“子类指针可以转父类指针”的两条规则成功的冲突到了一起
- C++new delete 动态申请二维数组
- new、delete、指向连续空间的指针、数组、空间释放、空间申请
- C++:多维数组的动态分配(new)和释放(delete)
- C++ 传值 避免 内存泄漏的一个技巧。[new 了以后,不一定要delete][修正,new后一定delete,没人帮你释放的。我错了,此文章已没任何意义了]
- (转/学习)C++ 方式的内存分配与释放 new 和 delete
- C++对象的动态建立与释放详解(new和delete)
- C++:多维数组的动态分配(new)和释放(delete)
- C与C++中内存分配释放-malloc,free,new,delete
- 在C++动态库中释放调用动态库程序中生成的指针new和delete 或 malloc和free
- C++:多维数组的动态分配(new)和释放(delete)
- C与C++中内存分配释放-malloc,free,new,delete
- C++ 方式的内存分配与释放 new 和 delete