C 中的指針與引用詳細(xì)解讀_第1頁(yè)
C 中的指針與引用詳細(xì)解讀_第2頁(yè)
C 中的指針與引用詳細(xì)解讀_第3頁(yè)
C 中的指針與引用詳細(xì)解讀_第4頁(yè)
C 中的指針與引用詳細(xì)解讀_第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C+中的指針與引用詳細(xì)解讀1、指針和引用的定義在深入介紹之前我們首先來(lái)看一下指針和引用的定義、指針和引用的區(qū)別,然后分別針對(duì)指針和引用展開(kāi)討論,深入細(xì)節(jié)為何有這些差異。指針的權(quán)威定義:InadeclarationTDwhereDhastheform*cv-qualifier-seqoptD1AndthetypeoftheidentifierinthedeclarationTD1is“derived-declarator-type-listT”,thenthetypeoftheidentifierofDis“derived-declarator-type-listcv-qualifier-seq

2、pointertoT”.Thecv-qualifiersapplytothepointerandnottotheobjectpointerto.摘自ANSIC+Standard注:可能有些讀者并不明白cv-qualifier-seqCV-qualifiers(CV限定符)CV-qualifiers有三種:const-qualifier(const限定符)、Volatile-qualifier(volatile限定符)、以及const-volatile-qualifier(const-volatile限定符)。const類(lèi)對(duì)象的非靜態(tài)、非mutable、以及非引用數(shù)據(jù)成員是const-quali

3、fied;volatile類(lèi)對(duì)象的非靜態(tài)、非引用數(shù)據(jù)成員是volatile-qualified;const-volatile類(lèi)對(duì)象的非靜態(tài)、非引用數(shù)據(jù)成員是const-volatile-qualified。當(dāng)CV-qualifiers用于限定數(shù)組類(lèi)型時(shí),實(shí)際上是數(shù)組成員被該CV-qualifiers限定,而非該數(shù)組類(lèi)型。復(fù)合類(lèi)型并不因其成員被CV-qualifier限定而被該CV-qualifier限定,也就是說(shuō),即使復(fù)合類(lèi)型的成員有CV-qualifier限定,該復(fù)合類(lèi)型也不是CV-qualified對(duì)象。引用的權(quán)威定義:InadeclarationTDwhereDhastheform&am

4、p;D1AndthetypeoftheidentifierinthedeclarationTD1is“derived-declarator-type-listT”,thenthetypeoftheidentifierofDis“derived-declarator-type-listcv-qualifier-seqreferencetoT”.Cv-qualifiedreferencesareill-formedexceptwhenthecv-qualifiersareintroducedthroughtheuseofatypedeforatemplatetypeargument,inwhich

5、casethecv-qualifiersareignored.摘自ANSIC+Standard上面這些定義初看有些難懂,如果是這樣的話,那說(shuō)明你對(duì)C+還不夠熟悉,你還有很長(zhǎng)的路要走。下面用通俗易懂的話來(lái)概述一下:指針-對(duì)于一個(gè)類(lèi)型T,T*就是指向T的指針類(lèi)型,也即一個(gè)T*類(lèi)型的變量能夠保存一個(gè)T對(duì)象的地址,而類(lèi)型T是可以加一些限定詞的,如const、volatile等等。見(jiàn)下圖,所示指針的含義:引用-引用是一個(gè)對(duì)象的別名,主要用于函數(shù)參數(shù)和返回值類(lèi)型,符號(hào)X&表示X類(lèi)型的引用。見(jiàn)下圖,所示引用的含義:2、指針和引用的區(qū)別首先,引用不可以為空,但指針可以為空。前面也說(shuō)過(guò)了引用是對(duì)象的別名

6、,引用為空對(duì)象都不存在,怎么可能有別名!故定義一個(gè)引用的時(shí)候,必須初始化。因此如果你有一個(gè)變量是用于指向另一個(gè)對(duì)象,但是它可能為空,這時(shí)你應(yīng)該使用指針;如果變量總是指向一個(gè)對(duì)象,i.e.,你的設(shè)計(jì)不允許變量為空,這時(shí)你應(yīng)該使用引用。如下圖中,如果定義一個(gè)引用變量,不初始化的話連編譯都通不過(guò)(編譯時(shí)錯(cuò)誤):而聲明指針是可以不指向任何對(duì)象,也正是因?yàn)檫@個(gè)原因,使用指針之前必須做判空操作,而引用就不必。其次,引用不可以改變指向,對(duì)一個(gè)對(duì)象”至死不渝”;但是指針可以改變指向,而指向其它對(duì)象。說(shuō)明:雖然引用不可以改變指向,但是可以改變初始化對(duì)象的內(nèi)容。例如就+操作而言,對(duì)引用的操作直接反應(yīng)到所指向的對(duì)象

7、,而不是改變指向;而對(duì)指針的操作,會(huì)使指針指向下一個(gè)對(duì)象,而不是改變所指對(duì)象的內(nèi)容。見(jiàn)下面的代碼:#include<iostream>usingnamespacestd;intmain(intargc,char*argv)inti=10;int&ref=i;ref+;cout<<"i="<<i<<endl;cout<<"ref="<<ref<<endl;intj=20;ref=j;ref+;cout<<"i="<<i&l

8、t;<endl;cout<<"ref="<<ref<<endl;cout<<"j="<<j<<endl;return0;對(duì)ref的+操作是直接反應(yīng)到所指變量之上,對(duì)引用變量ref重新賦值”ref=j”,并不會(huì)改變r(jià)ef的指向,它仍然指向的是i,而不是j。理所當(dāng)然,這時(shí)對(duì)ref進(jìn)行+操作不會(huì)影響到j(luò)。而這些換做是指針的話,情況大不相同,請(qǐng)自行實(shí)驗(yàn)。輸出結(jié)果如下:再次,引用的大小是所指向的變量的大小,因?yàn)橐弥皇且粋€(gè)別名而已;指針是指針本身的大小,4個(gè)字節(jié)。見(jiàn)下圖所示:從上面也可以

9、看出:引用比指針使用起來(lái)形式上更漂亮,使用引用指向的內(nèi)容時(shí)可以之間用引用變量名,而不像指針一樣要使用*;定義引用的時(shí)候也不用像指針一樣使用&取址。最后,引用比指針更安全。由于不存在空引用,并且引用一旦被初始化為指向一個(gè)對(duì)象,它就不能被改變?yōu)榱硪粋€(gè)對(duì)象的引用,因此引用很安全。對(duì)于指針來(lái)說(shuō),它可以隨時(shí)指向別的對(duì)象,并且可以不被初始化,或?yàn)镹ULL,所以不安全。const指針雖然不能改變指向,但仍然存在空指針,并且有可能產(chǎn)生野指針(即多個(gè)指針指向一塊內(nèi)存,free掉一個(gè)指針之后,別的指針就成了野指針)??偠灾?,言而總之它們的這些差別都可以歸結(jié)為”指針指向一塊內(nèi)存,它的內(nèi)容是所指內(nèi)存的地址;

10、而引用則是某塊內(nèi)存的別名,引用不改變指向?!?、特別之處const在這里我為什么要提到const關(guān)鍵字呢?因?yàn)閏onst對(duì)指針和引用的限定是有差別的,下面聽(tīng)我一一到來(lái)。常量指針VS常量引用常量指針:指向常量的指針,在指針定義語(yǔ)句的類(lèi)型前加const,表示指向的對(duì)象是常量。定義指向常量的指針只限制指針的間接訪問(wèn)操作,而不能規(guī)定指針指向的值本身的操作規(guī)定性。常量指針定義”constint*pointer=&a”告訴編譯器,*pointer是常量,不能將*pointer作為左值進(jìn)行操作。常量引用:指向常量的引用,在引用定義語(yǔ)句的類(lèi)型前加const,表示指向的對(duì)象是常量。也跟指針一樣不能利用引

11、用對(duì)指向的變量進(jìn)行重新賦值操作。指針常量VS引用常量在指針定義語(yǔ)句的指針名前加const,表示指針本身是常量。在定義指針常量時(shí)必須初始化!而這是引用天生具來(lái)的屬性,不用再引用指針定義語(yǔ)句的引用名前加const。指針常量定義”int*constpointer=&b”告訴編譯器,pointer是常量,不能作為左值進(jìn)行操作,但是允許修改間接訪問(wèn)值,即*pointer可以修改。常量指針常量VS常量引用常量常量指針常量:指向常量的指針常量,可以定義一個(gè)指向常量的指針常量,它必須在定義時(shí)初始化。常量指針常量定義”constint*constpointer=&c”告訴編譯器,pointer和

12、*pointer都是常量,他們都不能作為左值進(jìn)行操作。而就不存在所謂的”常量引用常量”,因?yàn)楦厦嬷v的一樣引用變量就是引用常量。C+不區(qū)分變量的const引用和const變量的引用。程序決不能給引用本身重新賦值,使他指向另一個(gè)變量,因此引用總是const的。如果對(duì)引用應(yīng)用關(guān)鍵字const,起作用就是使其目標(biāo)稱(chēng)為const變量。即沒(méi)有:Constdoubleconst&a=1;只有constdouble&a=1;總結(jié):有一個(gè)規(guī)則可以很好的區(qū)分const是修飾指針,還是修飾指針指向的數(shù)據(jù)畫(huà)一條垂直穿過(guò)指針聲明的星號(hào)(*),如果const出現(xiàn)在線的左邊,指針指向的數(shù)據(jù)為常量;如果co

13、nst出現(xiàn)在右邊,指針本身為常量。而引用本身與天俱來(lái)就是常量,即不可以改變指向。4、指針和引用的實(shí)現(xiàn)我們利用下面一段簡(jiǎn)單的代碼來(lái)深入分析指針和引用:#include<iostream>usingnamespacestd;intmain(intargc,char*argv)inti=1;int&ref=i;intx=ref;cout<<"xis"<<x<<endl;ref=2;int*p=&i;cout<<"ref="<<ref<<",i=&quo

14、t;<<i<<endl;上面的代碼用g+test.c編譯之后,然后反匯編objdump-da.out,得到main函數(shù)的一段匯編代碼如下:08048714<main>:8048714:55push%ebp8048715:89e5mov%esp,%ebpand$0xfffffff0,%esp/為main函數(shù)的參數(shù)argc、argv保留位置push%esipush%ebxsub$0x28,%esp8048717:83e4f0804871a:56804871b:53804871c:83ec28804871f:c744241c010000movl$0x1,0x1c(

15、%esp)/將0x1存到esp寄存器中,即inti=18048726:008048727:8d44241clea0x1c(%esp),%eax/esp寄存器里的變量i的地址傳給eax804872b:89442418mov%eax,0x18(%esp)/將寄存器eax中的內(nèi)容(i的地址)傳給寄存器中的變量ref,即int&ref=i804872f:8b442418地址8048733:8b00mov0x18(%esp),%eax/將寄存器esp中的ref傳給eax,即i的mov(%eax),%eax/以寄存器eax中的值作為地址,取出值給eax8048735:89442414的x,即x=r

16、ef8048739:c74424040089048048740:088048741:c7042440a00408mov%eax,0x14(%esp)/將寄存器eax中的值傳給寄存器esp中movl$0x8048900,0x4(%esp)movl$0x804a040,(%esp)call80486188048748:e8cbfeffff<_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKcplt>804874d:8b5424148048751:895424048048755:8904248048758:e85bfeffffmo

17、v0x14(%esp),%edxmov%edx,0x4(%esp)mov%eax,(%esp)call80485b8<_ZNSolsEiplt>movl$0x8048638,0x4(%esp)804875d:c74424043886048048764:088048765:890424mov%eax,(%esp)8048768:e8bbfeffffcall8048628<_ZNSolsEPFRSoS_Eplt>/從80487398048768這些行就是執(zhí)行"cout<<"xis"<<x<<endl;&quo

18、t;804876d:8b442418mov0x18(%esp),%eax/將寄存器esp中的ref傳到eax中movl$0x2,(%eax)/將0x2存到eax寄存器中l(wèi)ea0x1c(%esp),%eax/esp寄存器里的變量i的地址傳給eaxmov%eax,0x10(%esp)/將寄存器eax中的內(nèi)容(即i的地址)傳到8048771:c700020000008048777:8d44241c804877b:89442410寄存器esp中的p804877f:8b5c241c8048783:8b4424188048787:8b30mov0x1c(%esp),%ebxmov0x18(%esp),%e

19、axmov(%eax),%esi8048789:c74424040689048048790:088048791:c7042440a00408movl$0x8048906,0x4(%esp)movl$0x804a040,(%esp)call80486188048798:e87bfeffff<_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKcplt>804879d:8974240480487a1:89042480487a4:e80ffeffffmov%esi,0x4(%esp)mov%eax,(%esp)call80485b8

20、<_ZNSolsEiplt>movl$0x804890d,0x4(%esp)80487a9:c74424040d890480487b0:0880487b1:890424mov%eax,(%esp)call804861880487b4:e85ffeffff<_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKcplt>80487b9:895c240480487bd:89042480487c0:e8f3fdffffmov%ebx,0x4(%esp)mov%eax,(%esp)call80485b8<_ZNSols

21、Eiplt>movl$0x8048638,0x4(%esp)80487c5:c744240438860480487cc:0880487cd:890424mov%eax,(%esp)80487d0:e853feffffcall8048628<_ZNSolsEPFRSoS_Eplt>/這些行就是執(zhí)行"cout<<"ref="<<ref<<",i="<<i<<endl;"80487d5:b80000000080487da:83c42880487dd:5bmov$0

22、x0,%eaxadd$0x28,%esppop%ebx80487de:5e80487df:89ec80487e1:5dpop%esimov%ebp,%esppop%ebp80487e2:c3ret從匯編代碼可以看出實(shí)際上指針和引用在編譯器中的實(shí)現(xiàn)是一樣的:引用int&ref=i;8048727:8d44241clea0x1c(%esp),%eax/esp寄存器里的變量i的地址傳給eax804872b:89442418mov%eax,0×18(%esp)/將寄存器eax中的內(nèi)容(i的地址)傳給寄存器中的變量ref,即int&ref=i指針int*p=&i;8048777:8d44241clea0x1c(%es

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論