动态内存常用函数
malloc
申请未初始化的推内存,用两种方式初始化,for循环赋值,或者用memset
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int*p=(int*)malloc(100*sizeof(int));//开辟出来的是任意类型的空间,需要强制转换成int*
assert(p!=NULL);
memset(p,0,100*sizeof(int));
//或者用for循环初始换
for(int i=0;i<100;i++){
p[i]=0;
}//一般不用这种方式初始换
free(p);p=NULL;//防止空悬指针
指针p不能重复释放,为了避免该问题,对p进行置空操作。
如果参数ptr是NULL空指针,则free函数不做任何操作
p指向动态内存空间,修改p指向的位置,就会崩溃,不要用p++,可以用偏移量访问元素。
int main(){
int*ip=(int*)malloc(0);
if(nullptr==ip)cout<<"nullptr"<<endl;
else cout<<"not nullptr"<<endl;
return 0;
}//not nullptr
分配0字节ip不为空,指向了下越界标记
calloc
申请已被初始化的堆内存
malloc+for/memset <=> calloc
int*p=calloc(100,sizeof(int))//元素个数,每个元素的大小
assert(p!=NULL);
//......
free(p);
p=NULL;
calloc和malloc的关系,只是申请的空间初始化了
void*my_calloc(int count,size_t size){
int*s=(int*)malloc(size*count);
assert(s!=nullptr);
memset(s,0,count*size);
reutrn s;
}
realloc
已经动态申请堆内存空间,内存不够用,才扩容
分两个情况:后续未分配内存空间足够大,直接在后面扩容;后续未分配内存空间小于需要的空间 ,就会重新找一个大空间,将原有的内容复制过去,指针将会指向新的空间。以前的空间会自己释放。
int*p=(int*)malloc(10*sizeof(int));
assert(p!=NULL);
memset(p,0,10*sizeof(int));
//内存不足,扩容操作
int*q=realloc(p,20*sizeof(int))//元素个数,每个元素的大小
//万一扩容失败,q就会置空,以前p指向的内容不变,所以用q,原来指向的数据就会丢失
if(q==NULL){
error;
}
else{
p=q;
}
//......
free(p);
p=NULL;//防止野指针问题
free
1.如果参数ptr指向的空间不是动态开辟的,则free函数的行为是未定义的。
2.如果参数ptr是NULL空指针,则free函数不做任何操作
内存泄漏
内存泄漏:当开辟的动态内存不再需要使用时,他应该被释放,这样这块空间以后才能重新分配使用。而如果只开辟而不释放就会引起内存泄漏。通俗点说,如果不使用free释放动态分配的内存,那么那块内存将不再能被使用。