14.26 堆中对象数组 上一节的程序用10000个指针来记录10000个对象的地址,解决了对象丢失的问题,但是把10000个指针存放在栈中,也是一种资源浪费,栈的空间很小,容不得这样的浪费。那么如何解决这个问题呢? 我们可以利用对象数组来解决这个问题,声明一个由10000个对象组成的数组,然后用一个指针来指向该数组。这样用一个指针就可以操作10000个对象了。 我们直接将一个由10000个对象组成的数组放到堆里,用一个指针来指向数组,那么当程序结束的时候,只需要删除这个数组就可以了。 程序演示: #include<iostream> #include"Area.h" using namespace std; int main() { const int n = 10000; Area* const pone = new Area[n]; for (int i = 0;i < n;i++) { pone[i].set(i, i * 2); cout <<"Area["<<i <<"]:"; cout <<pone[i].getArea() <<endl; } delete[] pone; return 0; } Area* const pone = new Area[100000]; 该语句声明了一个指针pone,同时初始化了指针pone的值,让它指向由10000个Area对象组成的数组。这个数组保存在堆中。 由于new Area[100000]返回的是数组的地址,也就是pone[0]的地址。因此指针pone保存的就是pone[0]的地址,也就是该数组第一个对象的地址。 我们知道一个对象在堆中所占用的内存是根据它所拥有的变量来定义的,假如一个对象拥有4个占4字节的整型变量,那么该对象则占用16个字节的内存空间,同理,假如一个数组中拥有20个这样的对象,那么该对象数组则占用20乘以16等于320个字节的内存空间。 指针在内存中的访问也是根据这个原理,pone保存的是数组中第一个对象的地址,每个Area对象拥有2个int成员,每个int成员占4个字节,这样一个对象就占用8个字节。 pone+1后指向第二个对象,因此第二个对象的地址为数组首地址开始的第8个字节,而第三个对象的地址为数组首地址开始的第16个字节,其他以此类推。 当我们要访问数组元素的时候,可以: Area* const pone = new Area[n]; *pone = Area(10, 10); *(pone + 1) = Area(10, 20); *(pone + 2) = Area(10, 30); 这样给数组第一个元素赋值为Area(10, 10),第二个元素赋值为Area(10, 20),第三个元素赋值为Area(10, 30)。但是通常我们都不这样用,而是用数组的下标[]去访问数组元素。这样: Area* const pone = new Area[n]; pone[0] = Area(10, 10); pone[1] = Area(10, 20); pone[2] = Area(10, 30); 这样看起来很直观很方便,读代码时我们一眼就可以看出这是一个数组。 注意,万万不可这样: pone++; *pone = Area(10, 10); 这样看去上,pone指针自加后pone指针指向了数组的第二个元素,然后对第二个元素赋值为Area(10, 10),编译没有错,也能成功赋值。但要注意!我们在堆中创建的东西用完后需要用delete来释放,对于堆中数组,这样来释放: delete[] pone; 由于刚才我们对pone进行了自加,这里用delete释放的时候就会出错,因为pone自加后就没有指向数组第一个元素的地址了,系统无法正确的释放我们在堆中创建的数组所占的内存空间。就会出现程序崩溃。所以千万不要改变pone指针。 delete[] pone; []表示我们删除的是一个数组,如果忘记输入[],那么你删除的只是pone[0]。该错误带来的后果就是内存泄漏,因为其余对象你都没有机会删除了。 为了防止对pone指针的误操作,最好的办法是将它声明为常量指针,我们在一开始堆中创建数组的时候就这样: Area* const pone = new Area[n]; 将pone声明为常量指针后,我们就无法改变pone指针了,比如无法pone++,但是我们仍然可以正常的访问和修改pone指向的数组元素的值,pone[0]= Area(10, 10); 本节的程序形象地说明了对象数组的作用,与上节的程序相比,本节的程序对资源的浪费更少,因为只是在栈中保存了一个指针,而不是10000个。 【注意】 Area one[10000]; Area *one[10000]; Area *one = new Area[10000]; 第1种方式是声明了一个由10000个Area对象组成的数组,数组名叫one。 第2种方式是声明了一个由10000个指向Area的指针组成的数组,数组名为one。 第3种方式是声明了一个指针one,该指针指向由10000个Area对象组成的一个数组。 在这里要注意的是,第3种方式的one是一个指向数组的指针,也就是说one保存的是数组第1个元素的地址。 与LSGO一起学系列图文之 C++ 第1章 初识C++ 第2章 做一个简短的C++程序 第3章 初步了解函数 第4章 C++数据类型 第5章 if语句与逻辑运算符 第6章 面向对象 第7章 循环语句 第8章 指针 第9章 引用 第10章 深入函数 第11章 运算符重载 第12章 继承 第13章 虚函数 第14章 数组 14.25 指针数组 14.26 堆中对象数组 14.27 枚举常量与数组 14.28 多维数组 14.29 多维数组初始化 14.30 定义字符数组 14.31 二维数组输出图形 14.32 字符串数组 14.33 字符串的输入问题 14.34 strcat函数 14.35 strcpy函数 14.36 strcmp函数 14.37 strupr函数 14.38 strlwr函数 14.39 strlen函数 14.40 打印杨辉三角形 第15章 链表 第16章 多态 第17章 类的特殊成员 第18章 字符串 第19章 代码重用 第20章 友元类与嵌套类 第21章 流 第22章 命名空间 第23章 模板 第24章 异常和错误处理 第25章 补充内容 C++学习补充资料 华北电力大学LSGO软件技术团队成立于2010年09月25日,团队主要以机器学习和地理信息系统为主要研究方向,成立几年来为学校培养了大量优秀人才,他们或者就职于IBM、阿里巴巴、网易游戏、百度等IT企业,或者就读于中科院信安所、中科院计算所、中科院自动化所、中国科技大学、北京理工大学、武汉大学、华南理工大学、哈尔滨工业大学、华北电力大学等著名高校。 今年(2016年07月)毕业的李文乔同学保送到北京理工大学,安晟同学继续在华北电力大学读研究生,期间华硕公司,小米公司也希望团队推荐学生就业,综上,来LSGO软件技术团队学习可作为驻保高校学生,打发课余时间的一个不错选择。 如果对我们感兴趣,可以与我联系,通过考核后即可成为我们的一员。 请阅读以下代码(C#),得到联系方式: |
|