动态内存分配——malloc_free

概念

针对数组数据结构存在的问题:
定义数组时长度为常量,一旦完成定义,为数组分配的内存大小是固定不变的
1.设定数组太大,浪费内存空间
2.设定的数组太小,有可能不够用
怎么得到一块内存,刚好够用?

系统中存在一个内存管理器(MM,Memory Manager);MM用来管理一堆闲置的内存。被设计用于解决上述提出的问题。

MM功能:应用程序可以向MM申请(借出)一块指定大小的内存,用完之后再释放(还回)。
例如:

void* ptr=malloc(1024);  //申请,从MM借出内存
free(ptr);              //释放内存,还回MM

malloc、free函数

malloc函数
void* malloc(int size);

参数size:指定要申请的内存空间的大小
返回值:void* 指向这一块内存地址
注意:MM不关心内存存储数据的类型,所以返回void*
应用程序在使用malloc时,要把返回值转换成目标类型.例如,要申请一块空间存放1000个Contact()自定义对象,则:

int size=1000*sizeof(Contact);//先计算需要多少字节的内存空间
Contact* p=(Contact*)malloc(size);

所分配的内存和数组没有本质区别。数组本质上就是一块连续的内存。

free函数
void free(void* ptr);

ptr:之前malloc返回的内存地址。
返回值:void* 指向这一块内存地址。

例子

例1.
先计算需要多少字节的内存空间

  1. 申请内存,存贮char型数据,并得到其首地址
  2. 使用内存
  3. 释放内存
char* p=(char*)malloc(8);//申请8个字节的内存,并获取其首地址
for(int i=0;i<8;i++)//使用内存
{
   p[i]=i+1;
}
free(p);//释放内存

注意:上述例子的数据类型为基本类型char,也可以存储其它任意数据类型,也可以是自定义的类型。

struct Contact//自定义类型
{
   int id;
   char name[16];
}

int main()
{
int size=4*sizeof(Contact);//计算所需内存
Contact* p=(Contact*malloc(size);//申请内存,并强制类型转换为Contact型
p[0].id=1;
strcopy(p[0].name,"Jack");
p[1].id=2;
strcopy(p[1].name,"Marr");
}

优势

//用户决定要输入多少条数据
int n=0;
int scanf(“%d”,&n);

//用户需要多少,就分配多少内存
int size=n*sizeof(Contact);
Contact *p=(Contact *)malloc(size);

//释放
free(p);

总结

  1. MM是一个系统级的东西,所有的应用程序都向同一个MM申请内存。
  2. 内存被借出时,MM只是把他管理的内存标记了一下,表示该段内存已经被占用。
    (p0,n0),(p1,n1)…
  3. MM 极其慷慨:只要有人mallco ,就同意将内存借出,若不归还,他将永远不要求你free。所以用户应该及时自觉的free

使用原则:在需要的时候再申请,不需要的时候立即释放。

实际应用

对象指的一块内存
Contact a;//a是一个对象,及存放着一个对象的数据
Contact* p=(Contact*)malloc(siaeof(Contast);
确切的说:p指向一个对象。
例子:用Citizen表示一个市民,用Car表示一辆车,该市民起初没有车,但是未来可能有车

#include<stdio.h>
#include<stdlib.h>
#include<string>

struct Car
{
	char maker[32];//制造商
	int price;     //价格
};

struct Citizen
{
	char name[20]; //名字
	int deposite;  //存款
	Car* car;      //NULL时表示没有车(指针类型的car,表示有时候有,有时候无)
};

Citizen Jack = { "Jack",100,NULL };
void buy(Citizen* owner)
{
	//创建一个对象
	Car* car = (Car*)malloc(sizeof(Car));
	strcpy(car->maker, "Tesla");
	car->price = 10;
	//保存此对象(确切的说是记住指针)
	owner-> car = car;    //有车了
	owner->deposite -= car->price;//钱没了
}

//车辆报废
void discard(Citizen* owner)
{
	free(owner->car);//此对象被销毁(归还内存)
	owner->car= NULL;//回到无车状态
}
//车卖给被人
void sell(Citizen* owner, Citizen* other)
{
	Car* car = owner->car;

	car->price *= 0.5;
	other->deposite -= car->price;//半价出售
	other->car = car;             //别人拥有了这辆车

	owner->deposite += car->price;//车原主人收回部分成本
	//free(car);                  //不能free,车还在别人手中
	owner->car = NULL;            //回到无车状态
}
//再买一辆新车
void buy_new(Citizen* owner)
{
	free(owner->car);//释放资源
	owner->car = NULL;

	//创建一个对象
	Car* car = (Car*)malloc(sizeof(Car));
	strcpy(car->maker, "Tesla");
	car->price = 10;
	//保存此对象(确切的说是记住指针)
	owner->car = car;    //有车了
	owner->deposite -= car->price;//钱没了
}

int main()
{
	Citizen Jack = { "Jack",100,NULL};//先定义一个Citizen,起初没有车
	buy(&Jack);
	//discard(&Jack);
	Citizen a = { "ss",1000,NULL};
	sell(&Jack,&a);

	buy_new(&Jack);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值