malloc/free和new/delete

2012年06月13日 分类:学习笔记C++

如果使用堆栈存储和静态存储就能满足应用要求,那么就不要使用动态存储。

内存的分配方式有三种:从静态存储区域分配、在堆栈上分配和从堆或自由存储空间上分配。第三种也叫动态内存分配,相比前两种,动态分配要麻烦,而且更危险,所以尽量不要使用它。

要想使用动态存储,就要调用malloc/free和new/delete这两对组合。

1.malloc/free

malloc/free是c语言中的一对动态内存分配函数,他们是函数,原型如下:

void* malloc(size_t size);
void free(void* memblock);

malloc()返回的类型是void*,在调用时要显式地进行类型转换,将void*转换成所需要的指针类型。比如:

int *p=(int*)malloc(sizeof(int)*length);
free(p);

使用malloc时必须指定所开辟空间的大小,为了在不同系统中使用,通常使用sizeof()来计算所需要的空间大小。比如在32位系统中int类型是4字节的,16位则是2字节。使用完后记得释放内存,因为动态内存是开辟在堆中的,系统不会自动释放,所以malloc和free必须成对出现,不然就会造成内存溢出。使用free时只要传入内存指针即可,他的大小是事先知道的,不能释放两次,不然会出现双放的错误。

在这里说一道内存试题:

void GetMemory(char* p,int num)
{
 p=(char*)malloc(sizeof(char)*num);
}

void main()
{
 char* str=NULL;
 GetMemory(str,100);
 strcpy(str,"hello");
}

编译完全没问题,但在运行的时候会出错,问题出在最后的strcpy,其中的str为NULL。很不可思议,明明申请了内存却用不了。编译器总是要为函数的每个参数制作临时副本,当调用GetMemory时p和str并不是同一个指针,但他们指向同一个地址。在函数体内,p的指向被改变,也就是p的值变成了新开辟出来的动态内存的地址,而str仍然指向原来的地方(NULL),所以当运行的时候自然就出问题了。要想解决这个问题,我们可以使用指向指针的指针。

void GetMemory(char** p,int num)//引用:char*& p
{
 *p=(char*)malloc(sizeof(char)*num);//引用:p=...
}

void main()
{
 char* str=NULL;
 GetMemory(&str,100);//引用:GetMemory(str,100);
 strcpy(str,"hello");
}

当然我们也可以用指针的引用来完成这一操作,改法看注释。申请了别忘了释放哦!
当我们把指针当做形参传递时,可以改变它指向的地址的内容,而不是它指向的地址。

2.new/delete

不同于malloc/free,new/delete是c++的运算符,用起来比前者方便,比如:

int* p=new int[length];
int* i=new int;

这里我们不需要告诉他具体类型的长度,他会自动分配内存,但是在释放的时候有点不同了:

delete p;//wrong
delete []p;
delete i;

对于动态数组的释放要在前面加中括号,表示这是一个数组,否则系统只会释放数组的第一个元素,即p[0]。总之,不论是何种类型,new/delete和new[]/delete[]都应该配对使用。

作者:wuyuan 本文来自Wuyuan's Blog 转载请注明,谢谢! 文章地址: https://wuyuans.com/2012/06/new-delete-malloc-free