| 數(shù)組——這個C語言中的怪物,自從被直接繼承到C++中,便讓無數(shù)有識之士們前赴后繼、絞盡腦汁,試圖尋找一種可以動態(tài)增長的替代數(shù)據(jù)類型。當然,最著名的,應(yīng)該就是vector向量。但是,它的數(shù)據(jù)定義極其復雜,還有迭代的出現(xiàn),幾乎徹底摧毀了它僅存的一點優(yōu)勢。所以,引入MFC之后,微軟斬釘截鐵地拋棄了標準C++的模板庫。 CArray是MFC中非常重要的幾個類模板之一,其他的還有CList、CMap等,但它們的定義略微有點晦澀。以我自己的經(jīng)驗,在MFC中使用CArray定義動態(tài)數(shù)組是非常方便的。在MSDN中,CArray的聲明如下: template< class TYPE, class ARG_TYPE > class CArray : public CObject 參數(shù) TYPE 模板參數(shù),指定存儲在數(shù)組中對象的類型。TYPE是CArray返回的參數(shù)類型。 ARG_TYPE 模板參數(shù),指定用來訪問存儲在數(shù)組中對象的變量類型,通常是TYPE的引用。ARG_TYPE是傳遞給CArray的參數(shù)類型。 備注 CArray類支持與C中相似的數(shù)組,但是必要時可以動態(tài)收縮和增長。數(shù)組索引總是從0開始。你可以決定是固定數(shù)組上界還是允許當添加元素超過當前邊界時擴展數(shù)組。內(nèi)存被連續(xù)地分配到上界,即使一些元素可能為空。和C中數(shù)組一樣,CArray索引元素的訪問時間是不變的,與數(shù)組大小無關(guān)。 提示 在使用一個數(shù)組之前,使用SetSize建立它的大小和為它分配內(nèi)存。如果不使用SetSize,則為數(shù)組添加元素就會引起頻繁地重新分配和拷貝。頻繁地重新分配和拷貝不但沒有效率,而且會導致內(nèi)存碎片。 如果需要一堆數(shù)組中的個別數(shù)據(jù),必須設(shè)置CDumpContext對象的深度為1或更大。 此類的某些成員函數(shù)調(diào)用全局幫助函數(shù),它必須為CArray的大多數(shù)使用而定制。請參閱宏和全局量章節(jié)中的Collection Class Helpers。 當從一個CArray對象中移去元素時,幫助函數(shù)DestructElements被調(diào)用。當添加元素時,幫助函數(shù)ConstructElements被調(diào)用。 數(shù)組類的派生與列表的派生類似。 有關(guān)使用CArray類的更多信息,請參考Visual C++ Programmer's Guide中的論文集。 #include <afxtempl.h> 看到上面這么一大段文字是不是覺得有點頭暈?MSDN就是這樣的,不然怎么能體現(xiàn)出它的“權(quán)威”呢。其實不要覺得它很復雜,使用CArray類構(gòu)造動態(tài)數(shù)組非常簡單。首先,你需要包含頭文件Afxtempl.h,然后就可以定義自己的動態(tài)數(shù)組了。例如定義一個int型和CPoint型的動態(tài)數(shù)組: #include <afxtempl.h> CArray <int, int> num; CArray <CPoint, CPoint&> pt; // 也可以這樣:CArray <CPoint, CPoint> pt; 現(xiàn)在,我們構(gòu)造了兩個動態(tài)數(shù)組,按照MSDN的提示,我們要使用SetSize函數(shù)建立它的大小和分配內(nèi)存。(但其實這一步可以省略,而且我自己就是這么做的,雖然這不符合一個規(guī)范程序員的風格。)SetSize的函數(shù)原型是: void SetSize( int nNewSize, int nGrowBy = -1 ); 這個函數(shù)在MSDN中也有詳細的說明,我就不再去翻譯了。其中第一個參數(shù)指定數(shù)組大小,即數(shù)組中元素個數(shù)(必需大于或等于0)。對于第二個參數(shù),MSDN中有這樣一句話:如果使用了默認值,MFC以一種在大多數(shù)情況下能夠避免內(nèi)存碎片和最高效的方式去分配內(nèi)存。既然人家MSDN都這么說了,那我們第二個參數(shù)就使用它的默認值了。如果要加上這一步的話,可以這么寫(我們先不寫): num.SetSize(40); // 其實大小設(shè)為多少沒有關(guān)系,只要是你認為最合適的就行了 pt.SetSize(10); // 一般地,設(shè)得大些可以避免內(nèi)存碎片和提高效率,但所需空間越大 現(xiàn)在我們可以使用Add函數(shù)向數(shù)組中添加一個元素,也可以用GetAt函數(shù)來獲得一個元素。它們的函數(shù)的原型分別是: int Add( ARG_TYPE newElement ); TYPE GetAt( int nIndex ) const; Add函數(shù)向數(shù)組末尾增加一個元素,必要的話會擴展數(shù)組,它返回增加元素的索引值。GetAt函數(shù)返回給定索引的元素值。例如,我們可以這樣寫: for (int i=0; i<20; i++) num.Add(i); // 數(shù)組大小為20,數(shù)組中元素依次為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函數(shù),上面介紹的Add函數(shù)會在數(shù)組原來的大小上擴展數(shù)組,數(shù)組前面的元素全為0。即這時候數(shù)組的大小變成了50,前30個元素為0,后面的元素依次為0, 1, 2, … , 19。為了避免這種情況,這時候就需要使用SetAt函數(shù)來向數(shù)組中添加元素,SetAt函數(shù)設(shè)置給定索引的元素值,不允許擴展數(shù)組。其函數(shù)原型為: void SetAt( int nIndex, ARG_TYPE newElement ); 如果使用SetAt函數(shù),那么前面的代碼就要這么寫: for (int i=0; i<20; i++) num.SetAt(i, i); 如果要向數(shù)組中間插入或者刪除一個或多個元素,可以使用InsertAt和RemoveAt函數(shù)。它們的函數(shù)原型分別是: 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 // 那么數(shù)組中的元素是這樣的:0, 1, 2, 100, 3, 4, 5, … , 19 // num.InsertAt(3, 100, 2); // 在索引為3的位置向后插入兩個元素,均為100 // 則數(shù)組中元素是這樣的:0, 1, 2, 100, 100, 3, 4, 5, … , 19 CArray <int, int> numNew; for (i=0; i<10; i++) numNew.Add(i); // 新建數(shù)組的元素為:0, 1, 2, … , 9 num.InsertAt(5, &numNew); // InsertAt的第二個版本,插入一個數(shù)組 // 現(xiàn)在數(shù)組中的元素是這樣的:0, 1, 2, 100, 3, 0, 1, 2, … , 9, 4, 5, 6, … , 19 num.RemoveAt(2); // 移除索引為2的元素 // 數(shù)組中的元素變成這樣:0, 1, 100, 3, 0, 1, 2, … , 9, 4, 5, 6, … , 19 // num.RemoveAt(2, 3); // 從索引為2的位置開始,移除3個元素 // 數(shù)組中的元素變成這樣:0, 1, 0, 1, 2, … , 9, 4, 5, 6, … , 19 我們可以使用GetSize函數(shù)得到數(shù)組當前的大小(元素個數(shù)),可以使用GetUpperBound函數(shù)得到數(shù)組的上界(最大索引值),可以使用RemoveAll函數(shù)清空數(shù)組。跟C中一樣,我們還可以使用操作符[ ]來訪問數(shù)組元素,例如接著上面的例子: n = num.GetSize(); // n = 30 n = num.GetUpperBound(); // n = 29 n = num[2]; // n = 100 num.RemoveAll(); n = num.GetSize(); // n = 0 寫到這里,對CArray類的介紹已經(jīng)差不多了,使用上面的函數(shù)基本上可以滿足動態(tài)數(shù)組的操作。該類中還有一些其他函數(shù),需要進一步了解的可以查閱MSDN,在這里只是對CArray的常用函數(shù)作一個大概的介紹。 |