动态内存管理

目录

动态内存管理概念:

特性:

存在的意义:

二、认识动态内存函数:

1.malloc()和 free()

2.calloc()

3.realloc()

三、动态内存使用:


动态内存管理概念:

动态内存管理是在程序运行过程中,由程序员手动申请,手动释放的内存空间。

特性:

1.动态内存的生命周期是由程序员决定的,不会随所在作用域的退出而被释放。

2.动态内存是需要多少就申请多少(只受到硬件资源的限制),不会受数据类型的限制。

存在的意义:

这道题,如果我们没有学习动态内存管理,那我们该如何解决呢?

int* printNumbers(int n, int* returnSize) {
	//write code here
	//要求返回一个数组,数组中存储了1~最大的n位数
	int num = pow(10, n)-1;        //num就是最大的n位数
	static int arr[10000];     //因为我们怕不够用只能定义的很大
		for (int i = 0; i < num; i++) {
			arr[i] = i + 1;
	}
	*returnSize = num;
	return arr;

}

 这种解决方法存在的两个问题:

1.因为我们无法提前确定数组中要存储的数据个数,因此只能将数组定义的非常大来确保可以储存所有数据。

2.因为在函数中定义的变量是局部变量出了作用域数组就会被释放,为了不被释放只能定义为静态变量。

这两个问题我们都采用了特殊的处理方式来实现目的,但也存在一些缺陷:

1.如果只让存储一位数,那意味着10000个空间只使用了1个,存在大量的空间浪费。

2.静态变量的确延长了生命周期,但这种做法并不可取,如在多线程工作中,存在一个函数被多个执行流程同时执行。

所以动态内存管理的存在的必要性就很重要了!!

二、认识动态内存函数:

1.malloc()和 free()

c语言提供了一个动态开辟空间的方式:

void*  malloc( size_t _Size );

这个函数动态开辟了一个size大小的连续空间,并返回一个void型指针指向这片空间。

注意:

1.如果空间开辟成功则返回开辟好的指向这片空间的void*指针

2.如果开辟失败(系统空间不够-如今一般不存在),就会返回NULL指针,因此我们还是要检查malloc的返回值

3.malloc返回的类型是void*,我们在使用时要根据需要的类型进行转换

void free (void* ptr);

free()函数会释放ptr所指向的动态开辟的空间。

注意:

1.free()函数只会释放动态开辟的空间。

2.如果释放的空间是NULL就不做任何事。

3.同一块空间不可以多次释放程序会崩溃。

2.calloc()

void* calloc (size_t num, size_t size);

calloc()函数是开辟num个size大小的连续空间,并将各个空间的每个字节初始化为0。返回空间地址。

与malloc()相比calloc()在返回地址之前会将空间里的每个字节初始化为0.

同样在使用calloc()函数之后要使用free()释放空间避免空间泄露。

3.realloc()

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

1.对ptr所指向的空间进行扩容(ptr一定指向的是动态开辟的空间),扩容为size大小,扩容的同时会将数据拷贝过去。

2.如果原先ptr空间后面的空间足够则原地扩容,不拷贝数据。

3.如果原先ptr空间后面的空间不够则异地扩容,找一块足够的连续空间进行扩容将原数据拷贝到新空间并释放原空间。

返回值:返回新空间的起始地址。开辟失败则返回NULL

三、动态内存使用:

现在我们再看看刚才那道问题就有更好的处理方式.

#include <stdlib.h>
int* printNumbers(int n, int* returnSize) {
	//write code here
	//要求返回一个数组,数组中存储了1~最大的n位数
	int num = pow(10, n) - 1;
	int* ptr = (int*)malloc(sizeof(int) * num);
	for (int i = 0; i < num; i++) {
		ptr[i] = i+1;
	}
	*returnSize = num;
	return ptr;
}

现在我们使用的空间就是需要多少申请多少不存在资源的浪费问题。

那为什么动态申请的内存具有的特性,普通定义的变量内存没有呢?

因为在操作系统的设计中,包含了编译器设计中考虑了多种不同特性的内存的使用;

因此将一个程序所用的内存空间进行了不同区域的划分,不同区域的内存具有不同的特性。

       

一般情况下我们定义的临时变量和函数,所分配的内存空间是在栈上分配的。

1.地址的分配是从高到低。

2.这个区域分配的空间出了作用域就会被自动释放。

而我们手动申请的空间是从堆区分配的。

1.生命周期是我们自己管理的(忘记释放就会容易造成内存泄漏)

2.可以按需申请,减少资源浪费。

全局变量和静态数据的存储是在全局数据区域(静态区)

他的生命周期随程序结束而结束

以上就是本篇博客的全部内容啦 由于博主才疏学浅 所以难免会出现纰漏 希望大佬们看到错误之后能够

不吝赐教 在评论区或者私信指正 博主一定及时修正

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶丨之秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值