欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
實(shí)現真正意義上的二維動(dòng)態(tài)數組模板

實(shí)現真正意義上的二維動(dòng)態(tài)數組模板

作者:zyq654321

我們可以通過(guò)動(dòng)態(tài)數組的反例來(lái)確定動(dòng)態(tài)數組應該具有哪些特性。大家都知道以下的方式是定義一個(gè)靜態(tài)數組。

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

從上面可以看出,定義了靜態(tài)數組之后,無(wú)論程序如果使這個(gè)數組,該數組在內存中所占空間的大小,位置是確定不變的。

我們可以得出結論,對于編譯器,靜態(tài)數組的大小和空間是已知的,因此編譯器可以自動(dòng)為該數組分配空間。具體情況是:如果你定義了一個(gè)全局數組,編譯器將在數據區為你的數組分配一個(gè)空間;如果是個(gè)局部數組(比如定義在某一個(gè)局數中),編譯器為你的數組分配一個(gè)棧(Stack)空間。

從靜態(tài)數組的討論中我們得出動(dòng)態(tài)數組應具有的特性:在程序的運行中,動(dòng)態(tài)數組是大小應該是可變的。因些動(dòng)態(tài)組數的實(shí)現應該是基于動(dòng)態(tài)的分配內存基礎上。下面看這個(gè)例子:

假設我們建立一個(gè)工廠(chǎng)工人的數據庫,數據庫中有多個(gè)表各代表不同的車(chē)間。每個(gè)表中保存該車(chē)間職工的信息,為了代碼簡(jiǎn)單,可以只讓數據庫保存職工的姓名。

下面是一個(gè)InputWorkers函數,以車(chē)間為單位輸入全車(chē)間職工姓名,然后一次性將這些數據存入數據庫中。

void InputWorkers(){	int iCountOfWorkers, int iNo;	……	用戶(hù)輸入獲得車(chē)間的人數和車(chē)間號	……	string* iArray = new string[iCountOfWorkers];	……	用戶(hù)輸入車(chē)間所有職工的信息,并存在iArray數組中	……	StoreInDatabase(iArray, iNo ); //存入數據庫	delete [] iArray;}
在程序中iArray是個(gè)string指針,并不是數組。但是數組的原理和指針是一樣的,比如p[1]是指數組p中的第二個(gè)元素,但在實(shí)際尋址中是以p+1進(jìn)行的。所以我們可以這樣使用iArray[1]。

InputWorkers中的iArray根據車(chē)間的總人數來(lái)分配不同大小的空間。從這種意義上,可以認為iArray實(shí)現了動(dòng)態(tài)數組的功能。

如果iArray定義為一個(gè)靜態(tài)數組,那么iArray的大小是固定的,因此我們必須估計車(chē)間人數的一個(gè)上限。

string iArray[100];

靜態(tài)數組的速度是快于動(dòng)態(tài)數組。因為從理論上,棧在速度上是快于堆的。但是我們如果決定使用動(dòng)態(tài)數組在是因為節省空間的考慮。另外要注意靜態(tài)數組上限變化帶來(lái)的成本。我們必須重新設定上限以解決這個(gè)bug,然后重新編譯程序。如果你能控制程序的編譯,這沒(méi)問(wèn)題。但是,你要做是的為每一個(gè)用戶(hù)更新程序。沒(méi)有更新的用戶(hù)就可以遇到這個(gè)bug。想到這一點(diǎn),你就快樂(lè )不起來(lái)。

你可能會(huì )說(shuō),我設一下大一點(diǎn)的上限,超出它的可能性會(huì )非常小,而且內存的浪費也不會(huì )多大。比如最多一個(gè)車(chē)間200人,最少一個(gè)車(chē)間100人,那也只浪費了100空間?,F在機器的內存根本不在乎這么一個(gè)空間浪費。是的,你可以這么做,但是請繼續向下討論。

現在我們要將所有職工的姓名存入一個(gè)二維數組,數組的每一行表示一個(gè)車(chē)間,每行中的元素是職工的姓名。想想看,如果用靜態(tài)數組,你會(huì )浪費多空間。而且你還要為車(chē)間數加一個(gè)上限。這個(gè)例子并不好,因為工廠(chǎng)中的車(chē)間數應該是可以確定的。但是我可以換個(gè)角度說(shuō),我只要某幾個(gè)車(chē)間,也可能是所有車(chē)間,那么你是否還堅持呢?

說(shuō)了上面這些,只是少少的討論了一下動(dòng)態(tài)數組可能是使用情況?,F實(shí)中,尤其是大型軟件系統中動(dòng)態(tài)數組的使用其實(shí)很普遍。而且在C++的各種庫中也有數組的實(shí)現的類(lèi),通過(guò)調用相應的類(lèi)函數就可以對數組中的元素實(shí)現增/刪。而且也可以通過(guò)嵌套實(shí)現二維的動(dòng)態(tài)。這些類(lèi)或類(lèi)模板使用起來(lái)很容易。比如:

CAtlArray<int> iArray;iArray[0] = 1; // 出錯,iArray中并沒(méi)有元素iArray.Add(1);   // element 2iArray[0] = 1; // 可以,iArray中并有1個(gè)元素iArray[0] = 1; // 出錯,iArray中并只有1個(gè)元素
看了上面,你會(huì )覺(jué)得很煩,每當數組擴大時(shí)必須通過(guò)一個(gè)函數Add。但程序員們都會(huì )習慣的,我們會(huì )想這是應該為動(dòng)態(tài)數組付出的代價(jià)。再想一想二維數組,Add動(dòng)作的工作會(huì )讓你很是不爽。你會(huì )懷念靜態(tài)數組的操作方法,直接使用iArray[10] = 10,只要你定義的上限是大于是10的。而下面,我就是要討論這一種方法的實(shí)現。

首先我們希望有這樣的一維數組:

CDynamic1Dim<int> m_dim; // m_dim的大小是1
然后執行下面的語(yǔ)句:
m_dim[4] = 710;
此時(shí)m_dim的大小是5。

如何使m_dim[4] = 710在數組只有一個(gè)元素的情況下不會(huì )出錯而且增加數組的大小以使該語(yǔ)句成功?最為簡(jiǎn)單的方法是重載operator[]操作符。下面我們討論實(shí)現的細節。

template<typename T>class Dynamic1Dim{public:    Dynamic1Dim();    ~Dynamic1Dim();    T& operator[](int index);protected:    bool EnlargeDim(int iSize);public:    T*    m_pBuf;      int    m_iSize;};
上面定義一個(gè)模板類(lèi)Dynamic1Dim<T>。其構造函數如下:
//--------------------------------------------------// 構造函數template<typename T>Dynamic1Dim<T>::Dynamic1Dim(){    //數組的初始大小的1個(gè)T類(lèi)型對象    //分配一塊內存其大小為T(mén)型類(lèi)所占的空間    m_pBuf = (T*)malloc(sizeof(T));     //在內存空間中建立一個(gè)T型對象    new(m_pBuf) T();     m_iSize    = 1;}
在初始函數中我們設定數組的默認長(cháng)度為1。當用戶(hù)使用語(yǔ)句m_dim[4] = 710時(shí),重載的操作符被調用。
//--------------------------------------------------// operator [] template<typename T>T& Dynamic1Dim<T>::operator [](int index) {    // 如果下標是負值,拋出一個(gè)異常    if( index < 0 ) throw std::out_of_range(" Index shouldn''t be negative");     //檢查下標是否超來(lái)數組大小,如果超過(guò)則調用EnlargeDim擴大數組    if(index > m_iSize - 1)       EnlargeDim(index + 1);    Return m_pBuf [index];}//--------------------------------------------------// Enlargetemplate<typename T>bool Dynamic1Dim<T>::EnlargeDim(int iSize) {    // 重新分配一塊內存,其大小為擴大后T類(lèi)型數組的大小    m_pBuf = (string*) realloc(m_pBuf, sizeof(T) * iSize);     // 在擴大部分的內存空間上建立T類(lèi)型的數組對象,并調用其默認構造函數    for(int i = m_iSize; i < iSize; i++)    {       new(&m_pBuf[i]) T();    }    m_iSize = iSize;    return true;}
上面的代碼已基本實(shí)現了動(dòng)態(tài)一維數組的要求。但有一個(gè)點(diǎn)必須當心,就是數組空間的釋放問(wèn)題。在Dynamic1Dim的析構函數中必須釋放動(dòng)態(tài)分配的空間。
//--------------------------------------------------// Destructortemplate<typename T>Dynamic1Dim<T>::~Dynamic1Dim(){     // 調用T類(lèi)的析構函數    for(int i = 0; i < m_iSize; i++)    {       m_pBuf [i].~T();    }    // 釋放內存空間    free(m_pBuf);}
注意,m_pElem[i].~T()是必要的,因為T(mén)對象中也可能有內存的分配。如果沒(méi)有這句,T對象中分配的內存就無(wú)法釋放,其實(shí)這也是很多內存泄露的原因。

上面的代碼實(shí)現了動(dòng)態(tài)一維數組的模板。我們最后就要討論動(dòng)態(tài)二維數組的實(shí)現。

我們會(huì )希望有這樣的二維數組:

CDynamic2Dim<int> m_dim; // m_dim的大小是1*1
然后執行下面的語(yǔ)句:
m_dim[1][3] = 33;m_dim[4][10] = 710;
此時(shí)m_dim的大小是:0、2、3行都只有一個(gè)元素,1行有4個(gè)元素,4行有11個(gè)元素。 可以這樣設想,動(dòng)態(tài)二維數組是由數目不定的動(dòng)態(tài)一維數組組成的?;谶@種想法,我們看一下動(dòng)態(tài)二維數組的實(shí)現。
template<typename T>class Dynamic2Dim{public:    Dynamic2Dim();    ~Dynamic2Dim();    Dynamic1Dim<T>& operator[] (int index);protected:    bool EnlargeY(int nYSize);private:    int m_iYSize;    Dynamic1Dim<T>* m_pYBuf;    Dynamic1Dim<T> m;};
初始的二維數組應該是1*1大小的,因此Dynamic2Dim的構造函數應該如下
// Constructortemplate<typename T>Dynamic2Dim<T>::Dynamic2Dim(){    m_iYSize = 1;    m_pYBuf = (Dynamic1Dim<T>*) malloc(sizeof(Dynamic1Dim<T>));    m_pYElem = new(m_pYBuf) Dynamic1Dim<T>();}
在析構函數中釋放分配的內存空間:
// Desctructortemplate<typename T>Dynamic2Dim<T>::~Dynamic2Dim(){    for(int i = 0; i < m_iYSize; i++)    {       m_pYElem[i].~Dynamic1Dim();    }    free(m_pYBuf);}
需要為動(dòng)態(tài)二維數組重載操作符[],其實(shí)現如下
// operator[] overloadtemplate<typename T>Dynamic1Dim<T>& Dynamic2Dim<T>::operator[] (int index){    if(index < 0) throw std::out_of_range("negative index!");    if(index > m_iYSize - 1)       EnlargeY(index + 1);    return m_pYElem[index];}
從上我們可以知道,這里實(shí)現的是二維數組的縱向擴大,即根據二維數組的第一下標在決定是否擴大二維數組。這里須要注意的是返回值是一個(gè)一維動(dòng)態(tài)數組,由于一維動(dòng)態(tài)數組也重載了[]操作符,所以用戶(hù)可以最終得到一個(gè)指定的二維數組元素的引用(其類(lèi)型為T(mén))。

以上就是一個(gè)動(dòng)態(tài)二維數組的基本實(shí)現,說(shuō)它是基本實(shí)現,我是指它可以工作,但實(shí)際使用應該注意下而幾個(gè)問(wèn)題。

1.數組的動(dòng)態(tài)擴張是否在我們所期望的情況下進(jìn)行的??聪旅娴睦樱?/p>

Dynamic2Dim<string> arrString;arrString[3][4] = "34";string str = arrString[6][6];
根據動(dòng)態(tài)數組的定義,可以確定動(dòng)態(tài)二維數組進(jìn)行了二次擴張,第一次數組空間為4*n,這是我們期望的;第二次為7*n,在大多數情況下這不是我們期望的。(這里使用n是因為二維數組的行元素數目是不同的。)

在這里我給出一個(gè)解決的方法??梢允褂么眍?lèi)(proxy class)來(lái)區別上面二種情況,在第二種情況下可以?huà)伋鲆粋€(gè)異常。

2.動(dòng)態(tài)分配空間的大小。malloc須要調用操作系統的低級操作,我們不希望頻繁調用它,因此可以預先分配較大一些的空間。例如:用戶(hù)使用下標5時(shí),我們分配5*2的空間。

3.realloc的問(wèn)題。在已經(jīng)分配了較大內存空間時(shí),realloc會(huì )引起很大的開(kāi)銷(xiāo)(它必須進(jìn)行內存的拷貝以保持原有數據)。此時(shí)我們可以考慮使用malloc只分配所須的新的空間,盡管這樣有點(diǎn)復雜,但相比大塊的內存拷貝帶來(lái)的開(kāi)銷(xiāo)還是值得的。

4.因為動(dòng)態(tài)二維數組操作符[]返回的是一個(gè)動(dòng)態(tài)一維數組的引用,所以與普通二維數組相比,它有一些限制。

Dynamic2Dim<string> dim1;string dim2[10][10];string *p;p = dim2[3]; //Okp = dim1[3]; //Error. 因為dim1[3]返回的是Dynamic1Dim<string>類(lèi)型,而不是string類(lèi)型。
5.在實(shí)際使用時(shí),可以增加一個(gè)函數,返回當前數組的大小??梢允褂胕nline來(lái)減小引入其帶來(lái)的開(kāi)銷(xiāo)。

6.從二維動(dòng)態(tài)對象(不是指針)數組的角度,以上代碼并不適用于指針。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
VBA數組 | 從入門(mén)到精通(1)- 數組申明
VBA入門(mén)42:數組3
C++建立動(dòng)態(tài)二維數組
動(dòng)態(tài)申請二維數組
第8章 數組
VBA簡(jiǎn)單入門(mén)29:數組的數據來(lái)源(工作表、Array、Split)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久