动态内存简介

为什么要使用动态内存?

通常当我们声明一个数组时必须要指定数组的长度,但是数组的长度只有在程序运行的时候才知道,这是因为它所需的内存空间取决于输入数据的类型。这种方法虽然简单,但是它的缺点也是显而易见的,它极大的限制了程序的灵活性和健壮性。这种方式受到了人为的限制,一旦我们输入的数据元素超过了数组长度,它就无法处理这种情况,所以通常我们将数组的长度设置的很大,但是问题又来了,如果数组很大,我们输入的数据元素又很少,这样就极大地浪费了内存空间。更重要的一个问题是如果我们输入的元素超过了数组长度,有些编译器是不会报错的,它会把数组存满,剩余的元素不再存取,这样就使得程序输出一个错误的值,所以我们有的时候需要使用动态内存。

“动态内存分配”主要是为了解决那些在运行时才知道所需内存空间的数组的内存分配。

首先我们先来了解malloc、calloc、realloc、free这四个函数:

void *malloc(size_t size);

参数size:所需空间的字节个数

malloc实现内存的分配,当程序调用malloc时,malloc从内存池中提取出一块合适的且地址连续的内存(没有初始化),并把内存的首地址返回,但是malloc并不知道我们申请的是int类型还是float类型或者其他类型,所以malloc函数返回的是一个void*,可以转换成任何类型的指针,我们接受返回值时要对其进行强制类型转换。如果内存池中的空间不足,则malloc会返回一个空指针(NULL),所以使用malloc开辟的空间在使用时我们必须检查其返回值是否为空。

void *calloc(size_t n,size_t size);

参数n:所申请的元素的个数

参数size:每个元素所占的字节数

calloc也能实现动态内存的分配,它与malloc有两个不同的区别,第一使用calloc申请的空间会被初始化为0(在返回首地址之前),第二是参数不同,calloc需要两个参数,一个是元素的个数,一个是每个元素所占的字节数。

void *realloc(void* ptr,size_t newsize);

参数ptr:原内存的地址

参数newsize:连同旧内存一起,所需要的总内存大小

realloc用于修改一个已经分配好内存的内存块的大小,使用realloc这个函数可以使得原内存扩大或者缩小。

扩大内存:那么它会保留原内存的内容,并在原内存的后面开辟要增加的字节的空间,而不对新增加的内存进行初始化。如果原内存块后面的空间小于新增字节的大小,则realloc会在内存中重新找一块满足要求的空间,把原内存的内容复制过去,并返回新内存的地址,所以使用realloc后就不能使用旧内存的地址了,而应该使用新内存的地址。

缩小内存:realloc会将原内存尾部的部分内存释放掉。

如果realloc返回NULL就与malloc一样。

free(p);

free的参数必须是NULL,或者是malloc、calloc、realloc的返回值。

它的作用是释放内存(用完内存后必须释放,不然会发生内存泄漏,内存越用越少)。当然,当你释放完空间后p依然指向内存的起始位置,所以还要手动的将地址p赋值为空,即p = NULL。

使用free时一定要确保不再访问被释放内存的地址。

动态内存使用的常见错误:

1.没有检查内存是否分配成功

2.操作内存时越界

例如:申请一个数组arr[3],如果数组引用时下标小于0或大于2都会发生越界

3.使用free释放内存后,仍然访问被释放内存的地址



猜你喜欢

转载自blog.csdn.net/ypt523/article/details/80196065