MFC中动态数组CArray的使用
2010-04-27 10:21

数组——这个C语言中的怪物,自从被直接继承到C++中,便让无数有识之士们前赴后继、绞尽脑汁,试图寻找一种可以动态增长的替代数据类型。当然,最著名的,应该就是vector向量。但是,它的数据定义极其复杂,还有迭代的出现,几乎彻底摧毁了它仅存的一点优势。所以,引入MFC之后,微软斩钉截铁地抛弃了标准C++的模板库。
CArray是MFC中非常重要的几个类模板之一,其他的还有CList、CMap等,但它们的定义略微有点晦涩。以我自己的经验,在MFC中使用CArray定义动态数组是非常方便的。在MSDN中,CArray的声明如下:
template< class TYPE, class ARG_TYPE > class CArray : public CObject
参数
TYPE
模板参数,指定存储在数组中对象的类型。TYPE是CArray返回的参数类型。
ARG_TYPE
模板参数,指定用来访问存储在数组中对象的变量类型,通常是TYPE的引用。ARG_TYPE是传递给CArray的参数类型。
备注
CArray类支持与C中相似的数组,但是必要时可以动态收缩和增长。数组索引总是从0开始。你可以决定是固定数组上界还是允许当添加元素超过当前边界时扩展数组。内存被连续地分配到上界,即使一些元素可能为空。和C中数组一样,CArray索引元素的访问时间是不变的,与数组大小无关。
提示 在使用一个数组之前,使用SetSize建立它的大小和为它分配内存。如果不使用SetSize,则为数组添加元素就会引起频繁地重新分配和拷贝。频繁地重新分配和拷贝不但没有效率,而且会导致内存碎片。
如果需要一堆数组中的个别数据,必须设置CDumpContext对象的深度为1或更大。
此类的某些成员函数调用全局帮助函数,它必须为CArray的大多数使用而定制。请参阅宏和全局量章节中的Collection Class Helpers。
当从一个CArray对象中移去元素时,帮助函数DestructElements被调用。当添加元素时,帮助函数ConstructElements被调用。
数组类的派生与列表的派生类似。
有关使用CArray类的更多信息,请参考Visual C++ Programmer's Guide中的论文集。
#include <afxtempl.h>
看到上面这么一大段文字是不是觉得有点头晕?MSDN就是这样的,不然怎么能体现出它的“权威”呢。其实不要觉得它很复杂,使用CArray类构造动态数组非常简单。首先,你需要包含头文件Afxtempl.h,然后就可以定义自己的动态数组了。例如定义一个int型和CPoint型的动态数组:
#include <afxtempl.h>
CArray <int, int> num;
CArray <CPoint, CPoint&> pt; // 也可以这样:CArray <CPoint, CPoint> pt;
现在,我们构造了两个动态数组,按照MSDN的提示,我们要使用SetSize函数建立它的大小和分配内存。(但其实这一步可以省略,而且我自己就是这么做的,虽然这不符合一个规范程序员的风格。)SetSize的函数原型是:
void SetSize( int nNewSize, int nGrowBy = -1 );
这个函数在MSDN中也有详细的说明,我就不再去翻译了。其中第一个参数指定数组大小,即数组中元素个数(必需大于或等于0)。对于第二个参数,MSDN中有这样一句话:如果使用了默认值,MFC以一种在大多数情况下能够避免内存碎片和最高效的方式去分配内存。既然人家MSDN都这么说了,那我们第二个参数就使用它的默认值了。如果要加上这一步的话,可以这么写(我们先不写):
num.SetSize(40); // 其实大小设为多少没有关系,只要是你认为最合适的就行了
pt.SetSize(10); // 一般地,设得大些可以避免内存碎片和提高效率,但所需空间越大
现在我们可以使用Add函数向数组中添加一个元素,也可以用GetAt函数来获得一个元素。它们的函数的原型分别是:
int Add( ARG_TYPE newElement );
TYPE GetAt( int nIndex ) const;
Add函数向数组末尾增加一个元素,必要的话会扩展数组,它返回增加元素的索引值。GetAt函数返回给定索引的元素值。例如,我们可以这样写:
for (int i=0; i<20; i++) num.Add(i); // 数组大小为20,数组中元素依次为0, 1, 2, … , 19
int n = num.GetAt(10); // 由于索引是从0开始,得到第11个元素,也就是10
CPoint point(100,100);
pt.Add(point); // 或者不用定义point,直接pt.Add(CPoint(100,100));
需要特别说明的是,如果使用了SetSize函数,上面介绍的Add函数会在数组原来的大小上扩展数组,数组前面的元素全为0。即这时候数组的大小变成了50,前30个元素为0,后面的元素依次为0, 1, 2, … , 19。为了避免这种情况,这时候就需要使用SetAt函数来向数组中添加元素,SetAt函数设置给定索引的元素值,不允许扩展数组。其函数原型为:
void SetAt( int nIndex, ARG_TYPE newElement );
如果使用SetAt函数,那么前面的代码就要这么写:
for (int i=0; i<20; i++) num.SetAt(i, i);
如果要向数组中间插入或者删除一个或多个元素,可以使用InsertAt和RemoveAt函数。它们的函数原型分别是:
void InsertAt( int nIndex, ARG_TYPE newElement, int nCount = 1 );
void InsertAt( int nStartIndex, CArray* pNewArray );
void RemoveAt( int nIndex, int nCount = 1 );
接着上面的例子,我们可以这样写:
num.InsertAt(3, 100); // 在索引为3的位置插入元素100
// 那么数组中的元素是这样的:0, 1, 2, 100, 3, 4, 5, … , 19
// num.InsertAt(3, 100, 2); // 在索引为3的位置向后插入两个元素,均为100
// 则数组中元素是这样的:0, 1, 2, 100, 100, 3, 4, 5, … , 19
CArray <int, int> numNew;
for (i=0; i<10; i++) numNew.Add(i); // 新建数组的元素为:0, 1, 2, … , 9
num.InsertAt(5, &numNew); // InsertAt的第二个版本,插入一个数组
// 现在数组中的元素是这样的:0, 1, 2, 100, 3, 0, 1, 2, … , 9, 4, 5, 6, … , 19
num.RemoveAt(2); // 移除索引为2的元素
// 数组中的元素变成这样:0, 1, 100, 3, 0, 1, 2, … , 9, 4, 5, 6, … , 19
// num.RemoveAt(2, 3); // 从索引为2的位置开始,移除3个元素
// 数组中的元素变成这样:0, 1, 0, 1, 2, … , 9, 4, 5, 6, … , 19
我们可以使用GetSize函数得到数组当前的大小(元素个数),可以使用GetUpperBound函数得到数组的上界(最大索引值),可以使用RemoveAll函数清空数组。跟C中一样,我们还可以使用操作符[ ]来访问数组元素,例如接着上面的例子:
n = num.GetSize(); // n = 30
n = num.GetUpperBound(); // n = 29
n = num[2]; // n = 100
num.RemoveAll();
n = num.GetSize(); // n = 0
写到这里,对CArray类的介绍已经差不多了,使用上面的函数基本上可以满足动态数组的操作。该类中还有一些其他函数,需要进一步了解的可以查阅MSDN,在这里只是对CArray的常用函数作一个大概的介绍。

MFC中动态数组CArray的使用相关推荐

  1. MFC中动态创建控件以及事件响应实现方法

    本文实例讲述了MFC中动态创建控件以及事件响应实现方法,分享给大家供大家参考.具体实现方法如下: 动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态 ...

  2. MFC中动态创建控件以及添加事件响应

    本文实例讲述了MFC中动态创建控件以及事件响应实现方法,分享给大家供大家参考.具体实现方法如下: 动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态 ...

  3. MFC中动态创建button及添加响应事件

    MFC中动态创建button及添加响应的事件,主要步骤如下:  1.在头文件(**Dlg.h)中添加一个CButton类型,  例如:CButton btn;  2.在(**Dlg.cpp)的OnIn ...

  4. c语言中创建一个整数数组_VBA中动态数组的创建及利用方法

    大家好,后疫情时代一定会到来,各行各业,都将是一场战胜萧条的无声的战役.无论怎样,我们一定要坚信,疫情终将会过去,曙光一定会到来.后疫情时代将会是一个全新的世界,很多理念都将被打破,大多数人不会再享受 ...

  5. C语言中动态数组的作用,C语言实现动态数组

    前言 在纯C语言编程中,数组的创建必须是固定的大小,因为C语言本身没有提供动态数组这种数据结构,这是一个让习惯了使用高级语言编程的人转做C开发面临的一个很头疼的问题,本篇文章就将介绍如何使用纯C语言编 ...

  6. c语言中动态数组的实现

    在数组一章中,曾介绍过数组的长度是预先定义好的,在整个程序中固定不变.C语言中不允许动态数组类型.例如: int n;scanf("%d",&n);int a[n];用变量 ...

  7. C语言中动态数组的分配

    很多人在编写C语言代码的时候很少使用动态数组,不管什么情况下通通使用静态数组的方法来解决,但是现在发现这是一个相当不好的习惯,甚至可能导致编写的程序出现一些致命的错误. 尤其对于搞嵌入式的人来说,嵌入 ...

  8. MFC中动态创建控件及添加消息响应的方法实例

    动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的. 一.创建动态控件: 为了对照,我们先来看一下静态控件的创建. 放置静态控件时必须先建立一个容器,一般是对话框, ...

  9. MFC中动态获取/设置按钮的文字

    (1) 获取按钮控件的文本: CString tempstr; // 获取ID为ID_BUTTON_1按钮的文本内容 GetDlgItem(ID_BUTTON_1)->GetWindowText ...

最新文章

  1. iOS开发--面试总结(二)
  2. 面试:说说你对 HashMap 的认识?
  3. kibana智能检索发送多次_msearch —— 配置index pattern,同时设置时间段,就知道到底是在哪些索引里去查找数据了...
  4. github php项目,12月份GitHub上最热门的PHP项目
  5. 拷贝构造函数的调用以及浅拷贝与深拷贝的理解
  6. elon函数_Neuroink Elon麝香制造中的灾难
  7. 麦咭早教机器人_【今日吐槽】这句台词有毒!完全忘不了!(机器人免费送)...
  8. php基于新浪ip库获取城市,PHP基于新浪IP库获取IP详细地址的方法
  9. C++——二进制输出一个数以及输出double型位数过多情况
  10. 支付宝:“我的小程序”用户访问量一周激增165%
  11. java写算法之二叉搜索树查找
  12. 6.3.4 新的_Bool类型
  13. python高级编程总结
  14. 《解读NoSQL》——2.6 通过数据库分片获得水平扩展能力
  15. avalon2 非必填项的表单验证规则
  16. 正则学习之一:在js中使用正则表达式
  17. KKK下拉框lookupedit绑定数据时,添加一条固定数据
  18. http中get和post的区别
  19. 学习笔记9--汽车线控系统技术
  20. mongodb下载安装和基本操作

热门文章

  1. 制作模块-安装模块压缩包
  2. 初始化方法-在类的外部给对象增加属性的隐患
  3. Spring Boot定时任务-cron表达式
  4. Oracle之垂直水平分库分表(二)
  5. pip install python -32_pip安装python模块方法
  6. Java开源诊断工具 Arthas 发布v3.1.0
  7. Factory Method模式的误区:Factory Method模式是简化版的Abstract Factory吗?
  8. 非常便捷的本地Mock
  9. 点赞模块设计 - Redis缓存 + 定时写入数据库实现高性能点赞功能
  10. AM335X的USB otg网卡(RNDIS /Ethernet Gadget)调试