一. C语言中的动态内存的开辟与销毁方式:
1.开辟:
(1)只能用内存开辟函数开辟,函数原型为void *malloc(size_t size),我们需要传入的参数就是开辟内存的大小。
int* p = (int*)malloc(sizeof(int)*4);//开辟4个int大小的堆内存,也就是16个字节的内存空间
a.这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
b.如果开辟成功,则返回一个执行开辟好空间的指针。
如果开辟失败,则返回一个 NULL 指针,因此 malloc 的返回值一定要做检查也就是判空处理。
c.返回值的类型是void *,所以 必须指明类型。
(2) C语言还提供了一个函数叫calloc,也用来动态内存分配,原型:void *calloc(size_t num, size_t size);函数的功能是为num个大小为 size 的元素开辟一块空间,并把空间的每个字节初始化为0.
(3)扩容函数:函数原型:void *realloc(void *ptr, size_t size);
a.ptr是要调整内存地址。
b.size调整后新的大小。
c.返回值为调整之后的内存起始位置。
d.这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移到新的空间。
(4)内存的释放函数free,函数原型:
void free(void *ptr); //参数为某数据类型的指针
a.如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
b.如果参数ptr是NULL指针,则函数什么事都不做。
2.总结:
(1)开辟与释放在同一处,能做初始化工作,但是不能初始化常量内存块。
(2)开辟之后一定要判空。
二.C++上的内存开辟与销毁
1.具体操作方法:
int *p=new int(14)//开辟的同时可以初始化,初始化值加括号写入
delete p;//释放
int *arr=new int[10]//开辟一个长度为10,占用四十字节空间的一维数组(数组的开辟只能做零初始化)
delete []arr;//释放
/*
二维数组
*/
int **p=new int*[10];
for(int i=0;i<10;i++)
{
p[i]=new int [10];
} //开辟一个10*10*4字节大小的二维数组
for(int i=0;i<10;i++)
{
delete[] p[i];
}
delete []p; //释放
2.总结:
(1)开辟失败就会抛出异常(比如说内存空间不足时);
(2)可以开辟常量内存块:const int*p=const new int (10);
(3)new可以进行重定位,开辟的内存不一定在堆上,在自主存储区域;
int a=10;//在栈上开辟内存
char*p=new (&a);//此时开辟的空间在栈上也就是一个字节,指针指向原a内存空间头,此时delete命令就不能使用
三.两者进行对比
1、new、delete是关键字,而malloc、free是函数;
2、new实际上包括两个步骤:开辟空间、初始化,而malloc只是单纯开辟空间;
3、new可以开辟常量内存块const int*p=const new int (10),malloc不可以;
4、new可以调用malloc但是反过来不行;
5、new开辟内存后不用判空,因为如果申请失败会抛出异常然后终止;而malloc必须判空;
6、free(p)和delete p都是释放内存,但是对于非内置类型开辟的内存注意delete[]p的应用场景;