概念
针对数组数据结构存在的问题:
定义数组时长度为常量,一旦完成定义,为数组分配的内存大小是固定不变的
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.
先计算需要多少字节的内存空间
- 申请内存,存贮char型数据,并得到其首地址
- 使用内存
- 释放内存
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);
总结
- MM是一个系统级的东西,所有的应用程序都向同一个MM申请内存。
- 内存被借出时,MM只是把他管理的内存标记了一下,表示该段内存已经被占用。
(p0,n0),(p1,n1)… - 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;
}