当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 实现真正意义上的二维动态数组模板

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 实现真正意义上的二维动态数组模板


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 53 ::
收藏到网摘: n/a

实现真正意义上的二维动态数组模板

作者:zyq654321

我们可以通过动态数组的反例来确定动态数组应该具有哪些特性。大家都知道以下的方式是定义一个静态数组。

int iCount[10];int iCount[10][10];

从上面可以看出,定义了静态数组之后,无论程序如果使这个数组,该数组在内存中所占空间的大小,位置是确定不变的。

我们可以得出结论,对于编译器,静态数组的大小和空间是已知的,因此编译器可以自动为该数组分配空间。具体情况是:如果你定义了一个全局数组,编译器将在数据区为你的数组分配一个空间;如果是个局部数组(比如定义在某一个局数中),编译器为你的数组分配一个栈(Stack)空间。

从静态数组的讨论中我们得出动态数组应具有的特性:在程序的运行中,动态数组是大小应该是可变的。因些动态组数的实现应该是基于动态的分配内存基础上。下面看这个例子:

假设我们建立一个工厂工人的数据库,数据库中有多个表各代表不同的车间。每个表中保存该车间职工的信息,为了代码简单,可以只让数据库保存职工的姓名。

下面是一个InputWorkers函数,以车间为单位输入全车间职工姓名,然后一次性将这些数据存入数据库中。

void InputWorkers(){	int iCountOfWorkers, int iNo;	……	用户输入获得车间的人数和车间号	……	string* iArray = new string[iCountOfWorkers];	……	用户输入车间所有职工的信息,并存在iArray数组中	……	StoreInDatabase(iArray, iNo ); //存入数据库	delete [] iArray;}
在程序中iArray是个string指针,并不是数组。但是数组的原理和指针是一样的,比如p[1]是指数组p中的第二个元素,但在实际寻址中是以p+1进行的。所以我们可以这样使用iArray[1]。

InputWorkers中的iArray根据车间的总人数来分配不同大小的空间。从这种意义上,可以认为iArray实现了动态数组的功能。

如果iArray定义为一个静态数组,那么iArray的大小是固定的,因此我们必须估计车间人数的一个上限。

string iArray[100];

静态数组的速度是快于动态数组。因为从理论上,栈在速度上是快于堆的。但是我们如果决定使用动态数组在是因为节省空间的考虑。另外要注意静态数组上限变化带来的成本。我们必须重新设定上限以解决这个bug,然后重新编译程序。如果你能控制程序的编译,这没问题。但是,你要做是的为每一个用户更新程序。没有更新的用户就可以遇到这个bug。想到这一点,你就快乐不起来。

你可能会说,我设一下大一点的上限,超出它的可能性会非常小,而且内存的浪费也不会多大。比如最多一个车间200人,最少一个车间100人,那也只浪费了100空间。现在机器的内存根本不在乎这么一个空间浪费。是的,你可以这么做,但是请继续向下讨论。

现在我们要将所有职工的姓名存入一个二维数组,数组的每一行表示一个车间,每行中的元素是职工的姓名。想想看,如果用静态数组,你会浪费多空间。而且你还要为车间数加一个上限。这个例子并不好,因为工厂中的车间数应该是可以确定的。但是我可以换个角度说,我只要某几个车间,也可能是所有车间,那么你是否还坚持呢?

说了上面这些,只是少少的讨论了一下动态数组可能是使用情况。现实中,尤其是大型软件系统中动态数组的使用其实很普遍。而且在C++的各种库中也有数组的实现的类,通过调用相应的类函数就可以对数组中的元素实现增/删。而且也可以通过嵌套实现二维的动态。这些类或类模板使用起来很容易。比如:

CAtlArray<int> iArray;iArray[0] = 1; // 出错,iArray中并没有元素iArray.Add(1); // element 2iArray[0] = 1; // 可以,iArray中并有1个元素iArray[0] = 1; // 出错,iArray中并只有1个元素
看了上面,你会觉得很烦,每当数组扩大时必须通过一个函数Add。但程序员们都会习惯的,我们会想这是应该为动态数组付出的代价。再想一想二维数组,Add动作的工作会让你很是不爽。你会怀念静态数组的操作方法,直接使用iArray[10] = 10,只要你定义的上限是大于是10的。而下面,我就是要讨论这一种方法的实现。

首先我们希望有这样的一维数组:

CDynamic1Dim<int> m_dim; // m_dim的大小是1
然后执行下面的语句:
m_dim[4] = 710;
此时m_dim的大小是5。

如何使m_dim[4] = 710在数组只有一个元素的情况下不会出错而且增加数组的大小以使该语句成功?最为简单的方法是重载operator[]操作符。下面我们讨论实现的细节。

template<typename T>class Dynamic1Dim{public: Dynamic1Dim(); ~Dynamic1Dim(); T& operator[](int index);protected: bool EnlargeDim(int iSize);public: T* m_pBuf; int m