C++ Primer 多維數(shù)組的使用
多維數(shù)組
嚴(yán)格來(lái)說(shuō),C++語(yǔ)言沒有多維數(shù)組,通常所說(shuō)的多維數(shù)組其實(shí)是數(shù)組的數(shù)組。謹(jǐn)記這一點(diǎn),對(duì)今后理解和使用多維數(shù)組大有益處。
當(dāng)一個(gè)數(shù)組的元素仍然是數(shù)組時(shí),通常使用兩個(gè)維度來(lái)定義它:一個(gè)維度表示數(shù)組本身大小,另外一個(gè)維度表示其元素(也是數(shù)組)大小:
int ia[3][4];//大小為3的數(shù)組,每個(gè)元素是含有4個(gè)整數(shù)的數(shù)組 //大小為10的數(shù)組,它的每個(gè)元素都是大小為20的數(shù)組, //這些數(shù)組的元素是含有30個(gè)整數(shù)的數(shù)組 int arr[10][20][30]={0};//將所有元素初始化為0
按照由內(nèi)而外的順序閱讀此類定義有助于更好地理解其真實(shí)含義。在第一條語(yǔ)句中,我們定義的名字是ia,顯然ia是一個(gè)含有3個(gè)元素的數(shù)組。接著觀察右邊發(fā)現(xiàn),ia的元素也有自己的維度,所以ia的元素本身又都是含有4個(gè)元素的數(shù)組。再觀察左邊知道,真正存儲(chǔ)的元素是整數(shù)。因此最后可以明確第一條語(yǔ)句的含義:它定義了一個(gè)大小為3的數(shù)組,該數(shù)組的每個(gè)元素都是含有4個(gè)整數(shù)的數(shù)組。
使用同樣的方式理解arr的定義。首先arr是一個(gè)大小為10的數(shù)組,它的每個(gè)元素都是大小為20的數(shù)組,這些數(shù)組的元素又都是含有30個(gè)整數(shù)的數(shù)組。實(shí)際上,定義數(shù)組時(shí)對(duì)下標(biāo)運(yùn)算符的數(shù)量并沒有限制,因此只要慈意就可以定義這樣一個(gè)數(shù)組:它的元素還是數(shù)組,下一級(jí)數(shù)組的元素還是數(shù)組,再下一級(jí)數(shù)組的元素還是數(shù)組,以此類推。
對(duì)于二維數(shù)組來(lái)說(shuō),常把第一個(gè)維度稱作行,第二個(gè)維度稱作列。
多維數(shù)組的初始化
允許使用花括號(hào)括起來(lái)的一組值初始化多維數(shù)組,這點(diǎn)和普通的數(shù)組一樣。下面的初始化形式中,多維數(shù)組的每一行分別用花括號(hào)括了起來(lái):
int ia[3][4] = { // 三個(gè)數(shù)組,每個(gè)元素都是大小為4的數(shù)組 {0,1,2,3}, // 第一行的初始值 {4,5,6,7}, // 第二行的初始值 {8,9,10,11} // 第三行的初始值 }
其中內(nèi)層套著的花括號(hào)并非必需的,例如下面的初始化語(yǔ)句,形式上更為簡(jiǎn)潔,完成的功能和上面這段代碼完全一樣:
//沒有標(biāo)識(shí)每行的花括號(hào),與之前的初始化語(yǔ)句是等價(jià)的 int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
類似于一維數(shù)組,在初始化多維數(shù)組時(shí)也并非所有元素的值都必須包含在初始化列表之內(nèi)。如果僅僅想初始化每一行的第一個(gè)元素,通過(guò)如下的語(yǔ)句即可:
//顯式地初始化每行的首元素 int ta[3][4] = {{0},{4},{8}};
其他未列出的元素執(zhí)行默認(rèn)值初始化,這個(gè)過(guò)程和一維數(shù)組一樣。在這種情況下如果再省略掉內(nèi)層的花括號(hào),結(jié)果就大不一樣了。下面的代碼
//顯式地初始化第1行,其他元素執(zhí)行值初始化 int ix[3][4]={0,3,6,9};
含義發(fā)生了變化,它初始化的是第一行的4個(gè)元素,其他元素被初始化為0。
多維數(shù)組的下標(biāo)引用
可以使用下標(biāo)運(yùn)算符來(lái)訪問多維數(shù)組的元素,此時(shí)數(shù)組的每個(gè)維度對(duì)應(yīng)一個(gè)下標(biāo)運(yùn)算符。
如果表達(dá)式含有的下標(biāo)運(yùn)算符數(shù)量和數(shù)組的維度一樣多,該表達(dá)式的結(jié)果將是給定類型的元素;反之,如果表達(dá)式含有的下標(biāo)運(yùn)算符數(shù)量比數(shù)組的維度小,則表達(dá)式的結(jié)果將是給定索引處的一個(gè)內(nèi)層數(shù)組:
//用arr的首元素為ia最后一行的最后一個(gè)元素賦值 ia[2][3]=arr[0][0][0]; int(&row)[4]=ia[1];//把row綁定到ia的第二個(gè)4元素?cái)?shù)組上
在第一個(gè)例子中,對(duì)于用到的兩個(gè)數(shù)組來(lái)說(shuō),表達(dá)式提供的下標(biāo)運(yùn)算符數(shù)量都和它們各自的維度相同。在等號(hào)左側(cè),ia[2]得到數(shù)組ia的最后一行,此時(shí)返回的是表示ia最后一行的那個(gè)一維數(shù)組而非任何實(shí)際元素;對(duì)這個(gè)一維數(shù)組再取下標(biāo),得到編號(hào)為[31的元素,也就是這一行的最后一個(gè)元素。
類似的,等號(hào)右側(cè)的運(yùn)算對(duì)象包含3個(gè)維度。首先通過(guò)索引0得到最外層的數(shù)組,它是一個(gè)大小為20的(多維)數(shù)組;接著獲取這20個(gè)元素?cái)?shù)組的第一個(gè)元素,得到一個(gè)大小為30的一維數(shù)組;最后再取出其中的第一個(gè)元素。
在第二個(gè)例子中,把row定義成一個(gè)含有4個(gè)整數(shù)的數(shù)組的引用,然后將其綁定到ia的第2行。
再舉一個(gè)例子,程序中經(jīng)常會(huì)用到兩層嵌套的for循環(huán)來(lái)處理多維數(shù)組的元素:
constexpr size_t rowCnt=3,colCnt二4; intia[rowCnt][colCnt];//12個(gè)未初始化的元素 //對(duì)于每一行 for(size_t i = 0;i!=rowCnt;++i) { //對(duì)于行內(nèi)的每一列 for(stze_t j=0;j!=colCnt;++j) { //將元素的位置索引作為它的值 ia[i][j]= i *colCnt + j; } }
外層的for循環(huán)遍歷ia的所有元素,注意這里的元素是一維數(shù)組;內(nèi)層的for循環(huán)則遍歷那些一維數(shù)組的整數(shù)元素。此例中,我們將元素的值設(shè)為該元素在整個(gè)數(shù)組中的序號(hào)。
使用范圍for語(yǔ)句處理多維數(shù)組
由于在C++11新標(biāo)準(zhǔn)中新增了范圍for語(yǔ)句,所以前一個(gè)程序可以簡(jiǎn)化為如下形式:
size_t cnt = 0; for(auto& row:ia) //對(duì)于外層數(shù)組的每一個(gè)元素 for(auto&col:row){//對(duì)于內(nèi)層數(shù)組的每一個(gè)元素 col=cnt;//將下一個(gè)值賦給該元素 ++cnt;//將cnt加1 }
這個(gè)循環(huán)賦給ia元素的值和之前那個(gè)循環(huán)是完全相同的,區(qū)別之處是通過(guò)使用范圍for語(yǔ)句把管理數(shù)組索引的任務(wù)交給了系統(tǒng)來(lái)完成。因?yàn)橐淖冊(cè)氐闹?所以得把控制變量row和col聲明成引用類型。第一個(gè)for循環(huán)遍歷ia的所有元素,這些元素是大小為4的數(shù)組,因此row的類型就應(yīng)該是含有4個(gè)整數(shù)的數(shù)組的引用。第二個(gè)for循環(huán)遍歷那些4元素?cái)?shù)組中的某一個(gè),因此col的類型是整數(shù)的引用。每次迭代把cnt的值賦給ia的當(dāng)前元素,然后將cnt加1。
在上面的例子中,因?yàn)橐淖償?shù)組元素的值,所以我們選用引用類型作為循環(huán)控制變量,但其實(shí)還有一個(gè)深層次的原因促使我們這么做。舉一個(gè)例子,考慮如下的循環(huán):
for(const auto&row:ia) // 對(duì)于外層數(shù)組的每一個(gè)元素 for(auto col:row) // 對(duì)于內(nèi)層數(shù)組的每一個(gè)元素 cout<<col<<endl;
這個(gè)循環(huán)中并沒有任何寫操作,可是我們還是將外層循環(huán)的控制變量聲明成了引用類型,這是為了避免數(shù)組被自動(dòng)轉(zhuǎn)成指針。假設(shè)不用引用類型,則循環(huán)如下述形式:
for(auto row : ia) for(auto col:row)
程序?qū)o(wú)法通過(guò)編譯。這是因?yàn)?像之前一樣第一個(gè)循環(huán)遍歷ia的所有元素,注意這些元素實(shí)際上是大小為4的數(shù)組。因?yàn)閞ow不是引用類型,所以編譯器初始化col時(shí)會(huì)自動(dòng)將這些數(shù)組形式的元素(和其他類垣的數(shù)組一樣)轉(zhuǎn)換成指向該數(shù)組內(nèi)首元素的指針。這樣得到的row的類型就是int*,顯然內(nèi)層的循環(huán)就不合法了,編譯器將試圖在一個(gè)int*內(nèi)遍歷,這顯然和程序的初衷相去甚遠(yuǎn)。
要使用范圍for語(yǔ)句處理多維數(shù)組,除了最內(nèi)層的循環(huán)外,其他所有循環(huán)的控制變量都應(yīng)該是引用類型。
指針和多維數(shù)組
當(dāng)程序使用多維數(shù)組的名字時(shí),也會(huì)自動(dòng)將其轉(zhuǎn)換成指向數(shù)組首元素的指針。
定義指向多維數(shù)組的指針時(shí),千萬(wàn)別忘了這個(gè)多維數(shù)組實(shí)際上是數(shù)組的數(shù)組。
因?yàn)槎嗑S數(shù)組實(shí)際上是數(shù)組的數(shù)組,所以由多維數(shù)組名轉(zhuǎn)換得來(lái)的指針實(shí)際上是指向第一個(gè)內(nèi)層數(shù)組的指針:
int ia[3][4];//大小為3的數(shù)組,每個(gè)元素是含有4個(gè)整數(shù)的數(shù)組 int(*p)[4]=ia;//p指向吳有4個(gè)整數(shù)的數(shù)組 p=&ia[2];//p指向ia的尾元素
我們首先明確(*p)意味著p是一個(gè)指針。接著觀察右邊發(fā)現(xiàn),指針p所指的是一個(gè)維度為4的數(shù)組;再觀察左邊知道,數(shù)組中的元素是整
數(shù)。因此,p就是指向含有4個(gè)整數(shù)的數(shù)組的指針。
在上述聲明中,括號(hào)必不可少:
int*ip[4]//整型指針的數(shù)組 int(*ip)[4];//指向舍有4個(gè)整數(shù)的數(shù)組
隨著C++11新標(biāo)準(zhǔn)的提出,通過(guò)使用auto或者decltype就能盡可能地避免在數(shù)組前面加上一個(gè)指針類型了:
//輸出a中每個(gè)元素的值,每個(gè)內(nèi)層數(shù)組各占一行 //p指向含有4個(gè)整數(shù)的數(shù)組 for(auto p=ia;p!=ia+3;++p) //q指向4個(gè)整數(shù)數(shù)組的首元素,也就是說(shuō),q指向一個(gè)整數(shù) for(auto q=*p;q!=*p+4;++q) cout<< *q << ' '; cout<<endl;
外層的for循環(huán)首先聲明一個(gè)指針p并令其指向ia的第一個(gè)內(nèi)層數(shù)組,然后依次迭代直到ia的全部3行都處理完為止。其中遞增運(yùn)算++p負(fù)責(zé)將指針p移動(dòng)到ia的下一行。
內(nèi)層的for循環(huán)負(fù)責(zé)輸出內(nèi)層數(shù)組所包含的值。它首先后指針q指向p當(dāng)前所在行的第一個(gè)元素。*p是一個(gè)含有4個(gè)整數(shù)的數(shù)組,像往常一樣,數(shù)組名被自動(dòng)地轉(zhuǎn)換成指
向該數(shù)組首元素的指針。內(nèi)層for循環(huán)不斷迭代直到我們處理完了當(dāng)前內(nèi)層數(shù)組的所有元素為止。為了獲取內(nèi)層for循環(huán)的終止條件,再一次解引用p得到指向內(nèi)層數(shù)組首元素的指針,給它加上4就得到了終止條件。
當(dāng)然,使用標(biāo)準(zhǔn)庫(kù)函數(shù)begin和end也能實(shí)現(xiàn)同樣的功能,而且看起來(lái)更簡(jiǎn)潔一些:
//p指向ia的第一個(gè)數(shù)組 for(auto p=begin(ia);p!=end(ia);++p){ //q指向內(nèi)層數(shù)組的首元素 for(auto q=begin(*p);q!=end(*p);++q) cout<<*q<<' ';//輸出q所指的整數(shù)值 cout<<endl;
在這一版本的程序中,循環(huán)終止條件由end函數(shù)負(fù)責(zé)判斷。雖然我們也能推斷出p的類型是指向含有4個(gè)整數(shù)的數(shù)組的指針,a的類型是指向整數(shù)的指針,但是使用auto關(guān)鍵字我們就不必再煩心這些類型到底是什么了。
類型別名簡(jiǎn)化多維數(shù)組的指針
讀、寫和理解一個(gè)指向多維數(shù)組的指針是一個(gè)讓人不勝其煩的工作,使用類型別名能讓這項(xiàng)工作變得簡(jiǎn)單一點(diǎn)兒,例如:
using int_array=int[4];//新標(biāo)準(zhǔn)下類型別名的聲明 typedef int int_array[4];//等價(jià)的typedef聲明 //輸出ia中每個(gè)元素的值,每個(gè)內(nèi)層數(shù)組各占一行 for(int_array * p=ia;p!=ia+3;++p){ for(int*q=p;q!=*p+4;++q) cout<<*q<< ' '; cout<<endl; } 程序?qū)㈩愋汀?個(gè)整數(shù)組成的數(shù)組“和名為int_array,用類型名int_array定義外層循環(huán)的控制變量讓程序顯得簡(jiǎn)潔明了。
到此這篇關(guān)于C++ Primer 多維數(shù)組的使用的文章就介紹到這了,更多相關(guān)C++ 多維數(shù)組內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡(jiǎn)單說(shuō)說(shuō)STL的內(nèi)存管理
<STL 源碼剖析>將其描述為空間配置器,理由是allocator可以將其它存儲(chǔ)介質(zhì)(例如硬盤)做為stl 容器的存儲(chǔ)空間。由于內(nèi)存是allocator管理的主要部分,因此,本文以STL內(nèi)存管理為出發(fā)點(diǎn)介紹allocator2013-09-09COLORREF,COLOR,RGB,CString的轉(zhuǎn)化總結(jié)分析
實(shí)際的軟件開發(fā)過(guò)程中,常需要用到非.net平臺(tái)的代碼。這時(shí)候就可能碰到ColorRef(也就是以int類型代表的顏色值或是以DWORD值表示的顏色)。這跟.net平臺(tái)下的顏色的相互轉(zhuǎn)換MS并沒有直接實(shí)現(xiàn)2013-09-09C++實(shí)現(xiàn)隨機(jī)數(shù)生成的現(xiàn)代化封裝
在現(xiàn)代?C++?中,隨機(jī)數(shù)生成是許多程序設(shè)計(jì)中不可或缺的部分,例如游戲開發(fā)、算法設(shè)計(jì)、統(tǒng)計(jì)模擬等,本文將以一個(gè)封裝好的隨機(jī)工具類?Random?為例,深入剖析其功能的實(shí)現(xiàn)與使用,并引入相關(guān)知識(shí),幫助讀者觸類旁通,掌握?C++?隨機(jī)數(shù)的核心技巧2024-11-11C語(yǔ)言實(shí)現(xiàn)通訊錄小項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)通訊錄小項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05一文詳解如何實(shí)現(xiàn)QT的多語(yǔ)言切換(靜態(tài)+動(dòng)態(tài))
這篇文章主要給大家介紹了關(guān)于如何實(shí)現(xiàn)QT的多語(yǔ)言切換(靜態(tài)+動(dòng)態(tài))的相關(guān)資料,Qt是一款跨平臺(tái)的C++應(yīng)用程序開發(fā)框架,提供了一套豐富的工具和類庫(kù)來(lái)簡(jiǎn)化應(yīng)用程序開發(fā),文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06