再上一篇:8.3 指针数组与指向指针的指针变量
上一篇:8.4 指针与函数
主页
下一篇:8.6 引用和其它类型的指针
再下一篇:8.7 简单链表及其应用
文章列表

8.5 new与delete

《VC++程序设计基础》,讲述C++语言的语法和标准库,以及Visual C++ 函数库和MFC类库的使用,并附相关代码示例。

8.5.1 new和delete运算符

在程序的执行过程中,希望根据输入的值或计算的值来确定一个数组的大小时,到目前为止,是无法实现的。如:

int n;

cin>>n

float a[n];

C++是不允许这样定义数组的,因而,编译器认为数组a无效。但是:

int n;

cin>>n

float *p;

p = new float [n];

是允许的,当执行到new运算符时,动态地分配一个有n个元素的实型数组,并使p指向这个数组。这个数组的大小由n来确定的,所以它是可变的。这种动态地分配内存空间的方法,不仅可提高了程序的通用性,而且还有利于提高内存空间的利用率。

在C++中,new和delete运算符分别用于为指针变量动态分配内存空间和动态收回指针所指向的内存空间。使用new运算符为指针变量动态地分配内存空间,其格式为:

pointer = new type;

pointer = new type(value);

pointer = new type[ <表达式>];

其中pointer 是一个指针变量,type通常要与pointer的类型一致。第一种格式的功能是:分配由类型“type”确定大小的一个连续的内存空间,并把所分配内存空间的起始地址送给pointer。当分配不成功时,pointer的值为0。第二种格式除了完成第一种格式的功能外,将value的值作为所分配的内存空间的初始化值,对于这种格式,type只能是基本数据类型。第三种格式是分配指定类型的数组空间。

delete运算符用来将动态分配到的内存空间归还给系统,使用格式为:

delete pointer;

delete [ ] pointer;

delete [<表达式>] pointer;

其中pointer的值应为由new分配内存空间的起始地址。第一种格式,把pointer所指向的内存空间归还给系统;另二种格式都是把pointer所指向的一维数组的内存空间归还给系统。例8.26 动态内存空间分配。

#include

void main(void)

{

int *p1;

float *fp1,(*p)[10];

char *cp1;

p1 = new int; //A

fp1 = new float(2.5); //B

p= (float (*)[10] )new float[10]; //C

cp1 = new char; //D

*cp1 = 'A';

for(int i=0;i<10;i++) (*p)[i] = (float)i;

for (i =0;i <10;i++ ) {

cout << "(*p)[" <

if( (i+1)%5 == 0 ) cout<< '\n';

}

*p1 =25;

cout <<"*p1=" << *p1 <<'\n';

cout <<"*fp1=" << *fp1 <<'\n';

cout <<"*cp=" << *cp1 <<'\n';

delete p1; //E

delete fp1;

delete cp1;

delete [10] p;

}

执行程序时的输出为:

(*p)[0]=0 (*p)[1]=1 (*p)[2]=2 (*p)[3]=3 (*p)[4]=4

(*p)[5]=5 (*p)[6]=6 (*p)[7]=7 (*p)[8]=8 (*p)[9]=9

*p1=25

*fp1=2.5

*cp=A

程序中的A行,动态分配一个存放一个整数的内存空间,并使p1指向这个内存单元。B行分配一个存放实数的内存空间,并将它初始化为2.5。C行分配了由10个元素组成的一维数组空间。E行及其后的几行都是把用new运算符分配的内存空间归还给系统。

用new动态分配到的内存空间的内容是一些随机值,系统不对它们作任何初始化的工作。因此,直接读取这些值通常是无意义的。只有对分配到的内存空间进行初始化后,才能读取这些值。

8.5.2 使用new和delete应注意的事项

正确使用new和delete运算符是程序设计者的事,如果不能正确使用这二个运算符,会造成各种意想不到的错误。要正确使用这二个运算符,应注意以下几点:

1、用new运算符为指针变量所分配的存储空间,其初值是不确定的,所以在使用前要进行初始化。

2、对于大一点的程序,用运算符new分配空间后,要判其指针的值是否为0。若new运算符运算的结果为0,表示动态分配内存失败,这时应终止程序的执行,或进行出错处理。如:

float *p;

p = new float [1000];

if( p==0) {

cout<<”动态分配内存不成功,终止程序的执行!\n”;

exit(3);

}

3、动态分配存放数组的内存空间,或为结构体时分配内存空间时,不能在分配空间时进行初始化。如:

int *pi;

pi = new int [10](1,2,3,4,5,6,7,8,9);

是错误的。当定义了指向多维数组的指针变量时,可动态地为多维数组分配内存空间。若new运算符计算的指针类型与赋值运算符左操作数类型不一致时,必须进行强制类型转换。如:

float (*p1)[20], (*p2)[20];

p1= new float [20];

因p1实际上是用于指向二维数组的指针,而new运算的结果为一维数组的指针,编译时认为是错误的。正确的方法应该是:

p1= (float (*)[20]) new float [20]; //进行强制类型转换

p1= new float[1][20]; //分配二维数组的内存空间

表示分配一个二维数组的存储空间,这个数组只有一行,每行有10个实数。并将所分配的二维数组的起始行的行地址赋给p1。同理:

p2=new float [10][20];

是正确的,分配一个二维数组存储空间,每一行20个元素,共10行,使p2指向二维数组的第0行。而

int *p3;

p3 = new int [10][20];

是错误的,正确的表示方法为:

p3= (int *) new int [10][20];

p3= new int [10*20];

同理,用new运算符可为更多维数组动态分配内存空间。

4、用运算符new分配的内存空间的指针值必须保存起来,以便用delete运算符归还已动态分配的内存空间。否则会出现不可预测的错误。如:

float *fp, i;

fp=new float ;

*fp = 24.5;

fp = &i;

delete fp;

这里改变了fp的值,在调用delete时,fp已不是指向动态分配的存储空间。在执行程序的过程中出错。

注意:在程序中用new动态分配内存空间后,若没有用delete释放相应的内存空间,程序执行结束后,这部分的内存空间从系统中丢失;直到重新启动计算机,系统重新初始化时,系统才能利用这部分内存空间。所以用delete释放已动态分配到的内存空间是程序设计者的职责。

当动态分配了二维数组的存储空间后,在释放这部分存储空间时,要指明数组的行数。如:

int (*P)[100];

P= int [30][100];

......

delete [30] P; //A

A行将P所指向的二维数组空间都释放后,归还系统。但若把A行写为:

delete P;

这时仅释放二维数组的第0行所占用的存储空间。对于更多维数组的处理方法完全类同。

5、运算符delete 在释放动态分配的存储空间后,并不返回任何值。一旦释放了指针所指向的动态存储空间,不能再对其赋值。如:

float *p;

p=new float ;

......

delete p;

*p =5; //A

在A行中对*p的赋值是错误的,此时,并不知道p指向什么位置。