c/c++指针详解(二)----内存分配

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xbk123123/article/details/53262597

1、内存分配的三种方式:

1)、从静态存储区分配。数据的内存在程序编译时已经被分配,该内存在整个运行期间长期驻留,不会被释放;程序结束时,由操作系统自动释放。这类数据包括静态数据和全局数据。

2)、从栈空间分配。函数执行过程中,函数中的局部变量的内存,在栈上被分配;当函数调用完成后,随函数的返回空间也被释放。

3)、从堆空间分配。由开发者动态的申请内存,并手动的释放内存。

本文具体介绍动态内存分配,C语言中采用malloc、recalloc等函数分配内存;c++中使用new操作符申请内存。

malloc函数的返回值为void*,调用该函数时,需要显式的类型转化。返回值表示内存空间的首地址。如果该地址为NULL,表示系统没有满足的内存可供分配。因此在使用该地址之前,必须判断是否分配成功。例如:

int*p=(int*)malloc(sizeof(int)*10);

if(p != NULL)

{

......//使用该内存空间

}

在该内存使用完成后,需要开发者手动释放该内存:free(p):

这里需要注意:1)、调用free后,p和所指向的内存地址被断开,但是p的值仍然没有变化,此时如果调用p,将会出现错误,这时p就是一个野指针;因此当free(p);之后,应该将p的值赋为NULL,以免p再次调用出现错误。2)、虽然内存已经分配完成,但是并没有初始化,直接使用,取到的结果不正确。

4)、当malloc申请的内存不满足用户使用要求时,就需要重新分配内存,这时可以使用realloc函数。

void *realloc(
   void *memblock,
   size_t size 
);
memblock参数表示已经分配的内存地址的指针,即就是p;

size参数表示需要分配的字节数

该函数的返回值为,重新分配的内存空间的首地址。

realloc函数,在malloc函数已经分配的内存基础上再次扩充内存。realloc函数的返回值类型仍为void*。可以分三种情况来解释realloc。

情况一:需要分配的内存空间小于已经分配的空间。

那么这时只是从原来已经分配的内存空间中,将多余的空间释放,保留realloc函数需要的空间大小,将原来空间的的首地址赋值给realloc函数返回(这个地址和p的值是相同的);如果这样做的,可能会导致数据出错,因此一般不要缩小原内存空间;

情况二:需要分配的内存空间等于已经分配的空间。

将原来内存空间的首地址赋值给realloc函数返回;

情况三:需要分配的内存空间大于已经分配的空间。

1)如果原来的内存后,还有足够的空间,满足分配要求,那么直接在原来的内存的后面,分配适量的空间,并将原来空间的首地址赋值给realloc函数,返回;

2)如果原来内存后,没有足量的内存空间,满足分配要求,那么重新选择一块足量的空间分配,并将原来已经分配的空间的数据拷贝到新分配的内存中,将原指针p指向的空间释放。将新分配的空间首地址赋值给realloc函数返回,因此对于原来的空间,realloc函数在分配内存时,已经释放了原来的内存,不需要再次释放,否则会出错。

情况四:当分配的内存大小为0

系统是可以返回一个非NULL值,但是这个空间不能被使用。使用将会出错,效果等同于free(p);

情况五:当原来的指针为NULL

这种情况,的作用就相当于直接调用malloc函数一样;可以这样理解,NULL说明原空间没有分配成功,那么调用realloc函数,肯定需要分配一块新的内存空间,这不就相当于直接调用了malloc函数。

情况六:如果realloc函数调用失败

那么原来的空间地址不会被释放,保留原来的内存,该内存空间可以正常使用。


综上,在使用malloc函数时,需要注意几点:1)调用malloc函数后,需要判断内存是否分配成功;2)使用空间之前,需要给空间赋初始值;3)防止内存越界访问;4)释放内存空间之后free(p);,需要将原指针的值赋空(p=null;),以防再次使用产生错误,出现野指针;5)realloc函数对于原始的内存空间,在分配内存时已经做过处理,因此除realloc函数调用失败外,其余情况不能再次释放原空间内存,否则会出错。


2、既然malloc和free已经可以分配内存了,为什么还要引入new和delete?

首先需要明白,malloc和free是c语言中的c库函数,而new和delete是c++中的标识符;因此这两组拥有不同的性质;

接着,malloc和free不仅可以使用在C语言中,也可以使用在c++语言中,但是new和delete只是c++中特有的属性,在C语言中无法使用,因此new和delete有他的局限性;

再次,new和delete不仅需要分配内存空间,而且在面向对象的语言中,对于对象,还需要完成初始化,触发对象的构造和析构,这些操作是malloc和free无法完成的(笔者就在曾经实现链表的过程中,在结构体定义时,将一个数组元素定义为string类型的,在使用malloc申请内存后,调用过程中无法给该元素赋值。从这个例子中可以看出虽然malloc和new分配的内存大小相等,但是具体的内存内部工作还是有区别的)。

最后,malloc在分配内存时,需要开发者手动的指定元素的大小,并且返回值需要显式的类型转化;但是new就不需要指定和转化。


3、在c++中,既然new和delete可以完成所有分配的工作,为什么还要保留malloc和free?

这是因为c++编译器为了兼容c编译,是c中的所有函数可以在c++编译器上正常使用,因此保留了malloc和free

展开阅读全文
博主设置当前文章不允许评论。

没有更多推荐了,返回首页