最近Garena面試的過程當中,面試官提了一個問題,C++中引用傳遞和指針傳遞的區別?面試
根據本身的經驗,聯想到了swap函數,只知道既能夠用引用來實現,又能夠用指針傳遞來實現,至於兩者有何區別,本身還真沒有考慮過。安全
痛定思痛,受虐以後,趕忙彌補本身的知識漏洞。函數
經過在網上搜集資料,本身也整理了一下。spa
精簡版:指針
指針:變量,獨立,可變,可空,替身,無類型檢查;對象
引用:別名,依賴,不變,非空,本體,有類型檢查;生命週期
完整版:內存
1. 概念編譯
指針從本質上講是一個變量,變量的值是另外一個變量的地址,指針在邏輯上是獨立的,它能夠被改變的,包括指針變量的值(所指向的地址)和指針變量的值對應的內存中的數據(所指向地址中所存放的數據)。變量
引用從本質上講是一個別名,是另外一個變量的同義詞,它在邏輯上不是獨立的,它的存在具備依附性,因此引用必須在一開始就被初始化(先有這個變量,這個實物,這個實物纔能有別名),並且其引用的對象在其整個生命週期中不能被改變,即自始至終只能依附於同一個變量(初始化的時候表明的是誰的別名,就一直是誰的別名,不能變)。
2. C++中的指針參數傳遞和引用參數傳遞
指針參數傳遞本質上是值傳遞,它所傳遞的是一個地址值。值傳遞過程當中,被調函數的形式參數做爲被調函數的局部變量處理,會在棧中開闢內存空間以存放由主調函數傳遞進來的實參值,從而造成了實參的一個副本(替身)。值傳遞的特色是,被調函數對形式參數的任何操做都是做爲局部變量進行的,不會影響主調函數的實參變量的值(形參指針變了,實參指針不會變)。
引用參數傳遞過程當中,被調函數的形式參數也做爲局部變量在棧中開闢了內存空間,可是這時存放的是由主調函數放進來的實參變量的地址。被調函數對形參(本體)的任何操做都被處理成間接尋址,即經過棧中存放的地址訪問主調函數中的實參變量(根據別名找到主調函數中的本體)。所以,被調函數對形參的任何操做都會影響主調函數中的實參變量。
引用傳遞和指針傳遞是不一樣的,雖然他們都是在被調函數棧空間上的一個局部變量,可是任何對於引用參數的處理都會經過一個間接尋址的方式操做到主調函數中的相關變量。而對於指針傳遞的參數,若是改變被調函數中的指針地址,它將應用不到主調函數的相關變量。若是想經過指針參數傳遞來改變主調函數中的相關變量(地址),那就得使用指向指針的指針或者指針引用。
從編譯的角度來說,程序在編譯時分別將指針和引用添加到符號表上,符號表中記錄的是變量名及變量所對應地址。指針變量在符號表上對應的地址值爲指針變量的地址值,而引用在符號表上對應的地址值爲引用對象的地址值(與實參名字不一樣,地址相同)。符號表生成以後就不會再改,所以指針能夠改變其指向的對象(指針變量中的值能夠改),而引用對象則不能修改。
3. 總結
相同點:
都是地址的概念
不一樣點:
指針是一個實體(替身);引用只是一個別名(本體的另外一個名字)
引用只能在定義時被初始化一次,以後不可改變,即「從一而終」;指針能夠修改,即「見異思遷」;
引用不能爲空(有本體,纔有別名);指針能夠爲空;
sizeof 引用,獲得的是所指向變量的大小;sizeof 指針,獲得的是指針的大小;
指針 ++,是指指針的地址自增;引用++是指所指變量自增;
引用是類型安全的,引用過程會進行類型檢查;指針不會進行安全檢查;