动态内存分配
在程序中我们可以通过数组对大量数据和对象进行有效管理,但是声明产生的数组,其长度是固定的。如果程序需要处理的是一批个数不固定的数据,数据声明的太小,数据会存储不下,进而影响对数据的处理;但数组声明的太大,又必然会造成存储空间的浪费。
C++有两种分配内存的方式:静态内存分配 和 动态内存分配
- 静态内存分配:在编译阶段就分配好存储单元空间,在程序运行过程中,这些空间的大小是不可更改的,也无需对这些空间进行管理,编译时已将管理这些空间的代码加入目标程序,在作用域结束之后,自动将空间归还给系统。
- 动态分配空间: 指在程序语句中通过内存分配函数或者内存分配运算符取得的存储空间,这样得到的空间的大小,编译器是不知道的,完全由动态运行中的程序的当时的情况来决定;这些空间在使用完毕后,必须由程序语句显示的将其释放归还系统,否则会使得系统分配和利用的内存空间不断减少,直至枯竭,导致系统无法工作。
动态分配和释放内存有两种方法:一是利用标准函数,如malloc
和free
,它们的原型在头文件stdlib.h或alloc.h
中,这是从C语言中保留下来的方法;另外一种是用new
和delete
运算符,这是C++的方法。
- malloc函数和free函数
(1) malloc函数动态分配内存
malloc 函数的原型如下:
void *malloc(unsigned size);
malloc函数的功能是分配大小为size字节的内存单元,并返回所分配内存单元的地址,该地址是void类型,也就是说地址指向一个物理字节。分配内存可能成功,也可能失败。成功时,则返回所分配内存单元的首地址;失败时,则返回NULL。例如
int *p;
p = (int *)malloc(sizeof(int));
*p = 5;
虽然分配了int类型所占字节数的内存单元,但返回的是void类型的地址,通过强制类型转换后变成了int类型的地址,然后通过指针p对新分配的int类型内存单元赋值为5.
在程序运行时,还可以根据实际处理的数据个数动态地分配地分配一段连续的内存空间,及实现动态数组。假定要分配一个数组来存储一个班学生的成绩,而班级共n个人(n的值可以在程序运行时由键盘输入),则可用下面代码来实现:
float *score = (float*)malloc(sizeof(float)*n);
然后根据数组和指针的关系,用指针法或下标法来使用动态数组score里的每个元素。与前面声明的数组相比,动态分配可以根据运行时的实际需要分配内存,没有浪费空间,而使用起来又和数组一样方便!
(2) free函数动态释放内存,原型如下:
void free(void *ptr);
函数的功能是释放ptr指向的由malloc分配的内存空间,函数没有返回值。释放后的空间可以再次使用。
- new和delete 运算符
(1)运算符new动态分配内存
new运算符用于动态分配一块内存空间,其使用形式为:
指针变量 = new 数据类型(初始化参数)
其中,数据类型可以是标准数据类型,也可以是结构体类型,共用体类型,类类型;new运算符返回一个指向所分配的存储空间的第一个单元的指针,当没有足够的内存空间被分配时,将返回空指针0(NULL);new能够自动返回正确的指针类型,不必对返回指针进行类型转换;new分配的内存空间是连续的,可通过指针的移动访问所分配空间中的每个单元;new可以自动计所要分配空间的大小,不必使用sizeof()来计算所需的字节数。例如:
int *p;
p = new int(10);
声明p为int类型指针变量,通过new运算符动态分配了用于存放int型数据的内存空间,并将初始值 10存入该空间内,再将该内存空间的首地址赋给p.
对于基本数据类型,如果不希望在分配内存后设定初值,可以把小括号省略掉,例如
int *p = new int;
如果保留小括号,但是小括号中不写任何数值,则表示用0对该对象进行初始化。例如:
int *p = new int();
new还可以为数组动态分配内存空间,这是要再类型名后加上数组的大小,例如
int *ch = new int[10];
(2)运算符delete动态释放内存
delete运算符用于释放由new运算符分配的内存空间。由于内存空间有限,如果只取不换,系统就会很快因为内存用完而崩溃。所以,使用delete
运算符释放由new
运算符分配的内存空间是程序员必须会的一项工作。凡是由new运算符分配的内存空间,一定要在使用完后用delete释放。
delete运算符使用的形式为:
delete 指针;或者 delete []指针;
其中第二种形式用于释放为动态数组分配的内存空间。delete运算符后所跟的指针是由new运算符分配空间返回的指针,也可以是空指针(NULL).例如:
int *p = new int;
delete p;
char *ch = new char[10];
delete []ch;
使用delete运算符时,要注意两点:
- 由new运算符所分配的内存空间,只允许使用一次delete,不允许对同一块内存多次释放,否则会产生严重错误;
- delete运算符只能释放由new运算符分配的动态内存空间,程序中的变量,数组等的存储空间不得用delete运算符去释放。