学习C++动态内存的管理之前,我们先回顾一下C语言的动态内存管理,这是我写的一片关于C语言的动态内存管理博客:https://blog.csdn.net/porryCn/article/details/80280708。
简单的回顾:
C语言使用 malloc/calloc/realloc/free 进行动态内存管理。
int main() {
int* a = (int*)malloc(sizeof(int)*4);//malloc 开辟4个大小为4*sizeof(int)内存空间;
int* b = (int*)calloc(4, sizeof(int));//calloc 相比malloc,它的功能是开辟内存空间后的同时初始化为0;
int* c = (int*)realloc(b,sizeof(int)*10);//realloc 可以在指定地址空间或者非指定地址空间开辟指定大小的内存空间。
// c指针要开辟的空间显然比指定的指定空间要大,就要考虑到原地址空间的容量是否满足再开辟空间的大小,如果不够就要重新寻找合适的内存空间进行开辟。
//分配成功后,原地址空间自动释放;
//具体实例可以查看我的关于C语言动态内存管理相关博客。
free(a); //使用后要记得释放
free(c); //同上
//
return 0;
}
C++ 通过 new / delete 来进行动态内存管理()
:new(C++中 在堆中申请空间)
,delete(释放空间)
{
new/delete=动态管理对象;
new[]/delete[]=动态管理对象数组;
}
与malloc/free不同的地方在于,malloc/free是标准的库函数,而new/delete是操作符,前者是申请释放内存,后者是使用上是申请内存并初始化释放对象。
先做一个简单的栗子了解一下:
#include<iostream>
using namespace std;
int main() {
int* p1 = new int;//动态分配一个4字节(int)空间
int* p2 = new int(10);//动态分配一个4字节(一个int)的空间,并初始化为10。
int* p3 = new int[10];//动态分配40个字节(10个int)的空间。
delete p1;
delete p2;
delete[] p3;
return 0;
}
我们在C/C++ 使用动态内存管理的时候一定要记住一个原则,匹配使用!匹配使用!匹配使用!,否则会导致内存泄漏甚至程序的崩溃!!!
匹配使用原则:malloc(calloc/realloc)和free 以及new/new[] 和delete/delete[];
#include<iostream>
using namespace std;
//全局变量
int a = 1;
//全局静态变量
static int b = 2;
int main() {
//局部变量/静态变量
int a1 = 1;
static int b1 = 2;
char arr1[] = "studing make me happy";
char* arr2 = "yes";
int* a = (int*)malloc(sizeof(int)*2);
int* b = (int*)calloc(4,sizeof(int));
int* c = (int*)realloc(a,sizeof(int)*4);
free(a);
free(c);
int* p1 = new int;
int* p2 = new int(10);
int* p3 = new int[10];
delete p1;
delete p2;
delete[] p3;
return 0;
}
1)栈又叫堆栈,非静态局部变量/函数参数/返回值等等,栈是向下增长的。
2)内存映射段是高效的I/O映射方式,用于装载一块共享内存,用户可以通过接口创建共享内存,做进程间通信。
3)堆,用于程序运行是动态内存分配,堆上向上增长的。
4)数据段---存储全局数据和静态数据。
5)代码段---可执行的代码/只读常量。
----------------------------------------------------------------------------------------------------------------------
我们都知道C++ 兼容C,既然已经有了动态内存分配的方式,为何还有增加new/delete?
1.虽然两者都是动态内存分配的入口,但是malloc/free是C/C++标准库函数,而new/delete是操作符。
2.malloc需要自己计算类型的大小且返回值为void*,new自动计算类型的大小,返回值为对应类型的指针。
3.malloc/free只是动态内存的开辟和释放,而new/delete是调用了构造函数析构函数进行动态内存的开辟并初始化与清理释放空间。
------------------------------------------------------------------------------------------------------------------------
C++ 其他的动态内存管理接口:operator new/operator delete和operator new[]/operator delete[]
简单介绍一下(与malloc/free和new/delete相比):
1.用法和malloc/new一样,也是匹配使用,实际上就是malloc/new的封装。
2.operator new/operator new[]分配空间,operator delete/operator delete[]释放空间,他们不会调用构造和析构函数来初始话对象和清理对象。
--------------------------------------------------------------------------------------------------------------------
new / delete 和operator new / operator delete和malloc / free的关系
-----------------------------------------------------------------------------------------------------------------------------
new[]时底层处理的机制
看了一个大佬的博客,颇有感触,剪取一下大佬的总结:
对于内置类型:
new不会在首地址前4个字节定义数组长度。
delete 和 delete[]是一样的执行效果,都会删除整个数组,要删除的长度从new时即可知道。
对于自定义类型:
new []会在首地址前4个字节定义数组长度。
当delete[]时,会根据前4个字节所定义的长度来执行析构函数删除整个数组。
如果只是delete数组首地址,只会删除第一个对象的值。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
总结:
malloc/free 是C语言中用来管理动态内存的,而C++中使用new和delete来动态管理对象的,使用new[]/delete[]用来动态管理动态对象数组的。
在使用的时候,我们一定要匹配使用。
类型方面:malloc/free是库函数,new/delete是C++中的操作符。
事实上,new/delete的底层是由malloc/free实现的。malloc/free只负责开辟和释放内存,而new和delete不光负责开辟释放内存,还要负责掉弄构造和析构函数。new[]/delete[]在使用的时候,会调用N次构造和析构函数 。
在开辟内存的时候,malloc需要强制类型转换,并且技术开辟的内存大小,new则不用,自动计算类型大小,返回想对应的类型。
如果开辟失败。malloc返回NULL,而new会抛异常。失败后会调用一个new_handler函数,会尝试性的开辟内存,前提需要自己设置了new_handler函数。