如果遇到的面試多了叁怪,大抵會(huì)被問到這樣一個(gè)問題:數(shù)組和指針有什么區(qū)別审葬?這也是一道非常基礎(chǔ)但不乏精華的題目奕谭,所能得到的答案也可謂是五花八門涣觉,但不外乎如下幾類:概念復(fù)述,具體使用血柳,能否改變官册。
概念復(fù)述:數(shù)組是內(nèi)存中長(zhǎng)度確定的連續(xù)單元排列,而指針則是包含了單個(gè)單元地址的特殊單元难捌。
簡(jiǎn)單而又直接膝宁,直接列出概念,前者是一群?jiǎn)卧酰笳呤且粋€(gè)單元昆汹。但這顯然不是一個(gè)完整的答案。
具體使用:在全局下婴栽,數(shù)組與指針的長(zhǎng)度不同满粗,而對(duì)于函數(shù)而言,數(shù)組不能被傳入函數(shù)愚争,會(huì)被替換成一個(gè)指針映皆。
類似的答案還有很多,無非在強(qiáng)調(diào)數(shù)組和指針在使用(引用元素)上的種種差別轰枝。然而本質(zhì)上可以歸納為下列一句話:
數(shù)組在應(yīng)用元素時(shí)直接對(duì)數(shù)組地址符號(hào)的值作偏移捅彻,而指針在引用元素時(shí)則先讀取指針單元中的地址的值,再按該值進(jìn)行尋址鞍陨。
這里我為了突出兩個(gè)值的差別步淹,敘述的比較拗口从隆,其實(shí)這個(gè)答案的要素在于數(shù)組和指針的符號(hào)對(duì)于編譯器而言是兩個(gè)不同的東西,如果寫成代碼缭裆,事情其實(shí)很明了:
int a[10];
int* b = a;
cout << "a = " << a<< " &a = "<< &a << " sizeof(a) = " << sizeof(a) << endl;
cout << "b = " << b<< " &b = "<< &b << " sizeof(b) = " << sizeof(b) << endl;
上述的代碼昭示了幾個(gè)信息 數(shù)組的(首地址)值等于其取地址的結(jié)果键闺,而指針不然;數(shù)組與指針長(zhǎng)度是不一樣的澈驼,前者是所聲明數(shù)組的長(zhǎng)度辛燥,后者則僅僅是一個(gè)指針的大小。
回到剛才的討論:所有的符號(hào)都會(huì)被編譯器放在一張符號(hào)表中缝其,這張表也會(huì)標(biāo)注其相關(guān)的類別挎塌,對(duì)于數(shù)組,編譯器直接在出現(xiàn)這個(gè)符號(hào)的地方用那個(gè)地址去作替換内边,并完成相關(guān)的尋址和偏移工作榴都,因此會(huì)有a == &a。而對(duì)于指針漠其,則會(huì)先讀取存放在指針這個(gè)地址的單元的“值”缭贡,并把該值作為一個(gè)待尋地址,對(duì)其進(jìn)行尋址辉懒。簡(jiǎn)而言之阳惹,數(shù)組是地址符號(hào),指針是存值單元眶俩,指針多了一次讀取的步驟莹汤。而這樣的差異,則造成了數(shù)組與指針在所有使用細(xì)節(jié)上的不同颠印。
能否改變:數(shù)組不能改變纲岭,指針可以改變。
這個(gè)切入點(diǎn)在我看來可以說有些刁鉆了线罕,因?yàn)橐话愣灾钩保粫?huì)有人會(huì)覺得數(shù)組本身(地址)有什么修改的意義,因而這樣的角度有些刻意為之钞楼。然而要較真地去剖析喇闸,不得不承認(rèn)事實(shí)確實(shí)如此。從這個(gè)角度切入的人一般會(huì)認(rèn)同一種觀點(diǎn)询件,即數(shù)組與指針在本質(zhì)上沒有差別——均為指針燃乍,不過數(shù)組多了一個(gè)const限定。因此如下的代碼是不合法的:
Int a[10];
++ a;
編譯器給出的解釋為:表達(dá)式必須是能修改的左值宛琅。這恰也符合試圖修改const的情況刻蟹。
由此來看,上述的觀點(diǎn)完全成立嘿辟,但是考慮到第二個(gè)角度舆瘪,這個(gè)觀點(diǎn)又明顯相悖片效,這里我不打算深究數(shù)組的本質(zhì),畢竟要不要把數(shù)組理解為指針確實(shí)是個(gè)因人而異的話題英古,這里我選擇文字上做一個(gè)妥協(xié)淀衣,在最終的敘述上作一點(diǎn)修正:數(shù)組是一個(gè)const地址符號(hào),而指針則是一個(gè)非const的存址單元哺呜。
抽象觀念:數(shù)組是一個(gè)元素內(nèi)在關(guān)聯(lián)的線性表,而指針是一個(gè)獨(dú)立的迭代器
一般而言箕戳,如果能系統(tǒng)地從上述角度去表述這些差異某残,再畫上一兩張好看的圖示,可以說是非常完整了陵吸,然而我在閱讀Andrew Koenig / Barbara Moo的《C++沉思錄》時(shí)玻墅,作者提出了這樣一種觀點(diǎn)——數(shù)組(或者索引)本身提供了特殊的抽象含義,那些偏移本身就具有其意義壮虫,即使數(shù)組消失了也是如此澳厢。而指針的價(jià)值在于通過指針,便提供了額外的對(duì)象信息囚似,能夠用來構(gòu)造出更通用的程序剩拢。
上述的區(qū)別可以說相當(dāng)?shù)奶亓ⅹ?dú)行了,我認(rèn)為作者在此處不是從語(yǔ)法或?qū)崿F(xiàn)上饶唤,而是更多地從算法或抽象觀念的角度上來理解問題徐伐,看起來有些抽象,其實(shí)這個(gè)觀念是很直觀的募狂,要說明這個(gè)問題,請(qǐng)直接讀一讀如下的代碼吧:
a[2] = 3;
*(a + 2) = 3;
兩句代碼實(shí)現(xiàn)了一樣的功能性穿,但卻給了人不一樣的感覺雷滚。對(duì)于第一句,我們會(huì)說:給a的第二個(gè)元素賦值3胯舷;而對(duì)于第二句桑嘶,除非我們明白地知道a是一個(gè)數(shù)組躬充,否則我們往往會(huì)說:給a后面的第二個(gè)單元賦值3。這個(gè)表述上的差異正如作者所言以政,索引本身具有含義盈蛮,它表征了各元素的內(nèi)在聯(lián)系,數(shù)組的長(zhǎng)度情況殊轴,以及數(shù)組作為一個(gè)整體而存在等諸多概念旁理。而指針則更加獨(dú)立,即使它被放入一個(gè)指針孽文,也往往被割裂而存在夺艰。
至于說指針提供了對(duì)象信息,我認(rèn)為有些晦澀了郁副。對(duì)此我的理解是提供索引來進(jìn)行元素訪問時(shí)解引用過程默認(rèn)發(fā)生了,而指針則需要手動(dòng)解引用烹植,顯然解引用后的對(duì)象便被限定了類型愕贡,而指針則可以通過多態(tài)等手段有著更多發(fā)揮空間。這個(gè)解釋也有些刻意為之了墩虹,希望日后能悟到新的見解吧憨琳。
總而言之篙螟,數(shù)組與指針的差異:可以從概念復(fù)述,具體使用惧所,能否改變和抽象觀念四個(gè)方面來思考下愈。有的觀點(diǎn)有些過于刁鉆势似,但這也表明了C++的魅力所在——多去思考,便能窺見新天地障簿。