前言:
c++的创始人为了解决一些自定义类型创建时候的初始化等问题,开创了new/delete新的操作符,所以下面我们主要围绕这两位新角色来展开。
首先我们得知道,有哪些内存的区域:
栈 ,堆,静态区(数据段),常量区(代码段),我们看下图:
1.new和delete
1.1 内置类型情形
基本与c语言中的malloc,free等没有太大区别
1.2 自定义类型情形
1.new:调用operator new函数申请空间,在申请的空间上执行构造函数,完成对象的构造。
2.delete:在申请的空间上调用析构函数,将对象中的资源清理,然后调用operator delete来释放对象的空间。
3.new A[N](A是某自定义类型的类名):实际上也是调用多次operator new来完成N个对象的空间申请;然后再申请的空间上执行N次构造函数。
3. delete []:在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理, 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间
(补充)1.3 operator new与operator delete函数
new和delete是操作符,系统提供了operator new 和operator delete两个全局函数(不是运算符重载):
new实际底层调用operator new来申请空间,operator new实际也是调用malloc
delete实际底层调用operator delete来释放空间,operator delete实际调用free
new实际上是调用 operator new函数,这个函数中有malloc和抛异常(当mallloc失败的时候,系统会自动提示异常,所以不用我们自己去写malloc的失败判断)
2 .new/delete和malloc/free不可混用
对于一般的内置类型,new和free,不会出现问题;但是如果是自定义类型,则可能会出现问题。
我们举一个例子,如果是如下的代码:
stack *ptr=new Stack[10];
free(ptr);
这种情况下,会报错,但不是因为没有对自定义类型调用析构函数二造成的内存泄露(内存泄漏一般不会被编译器检测到)导致的,而是在new T[n]开辟空间的时候,这个n是用来指示析构的次数的,内存会在原来首地址之前开辟一个空间来存储这个次数n。
因为前面存储次数的空间没有释放,导致空间释放不完全,这才导致的报错。
但是尽管内存泄漏没有报错,我们依然要严格地处理来防止内存的泄露。
3.内存泄露类型
1.堆的内存泄露
堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new 等从堆中分配的一块存, 用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那 么以后这部分空间将无法再被使用,就会产生Heap Leak。
2.系统资源泄漏指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统 资源的浪费,严重可导致系统效能减少,系统执行不稳定。