引用&行內函數
阿新 • • 發佈:2021-01-23
引用
- 概念
引用是一個別名,不是新定義一個新變數。編譯器不會給引用變數重新分配空間,引用變數和其引用的實體共用同一份記憶體空間。 - 特性
a.引用變數在定義時必須要初始化
b.一個變數可以有多個引用
c.引用變數一旦引用一個實體後,就不能再去引用其他的實體 - 三種傳參方式區別
1.傳值
優點:可以對外部的實參起到保護作用,不會因為對形參的改變而引起實參的修改
缺點:a.不能通過形參改變外部的實參(因為形參是實參的一份拷貝,在函式體中修改形參實際修改的是實參的一份拷貝);b.傳參的效率低下
2.傳地址
優點:a.可以通過形參改變外部的實參;b.不需要對實參進行拷貝,傳參的效率高、節省空間
缺點:a.在不需要通過形參改變外部實參的情況下,程式碼的安全性不高(但是可以使用const避免);b.每次再次使用的時候要進行判空,程式碼的可讀性不高
優點:a.對形參進行修改可以達到對實參的改變;b.傳參效率高,節省空間;c.程式碼的可讀性高
缺點:在不需要通過形參改變外部實參的情況下,程式碼的安全性不高(但是可以使用const避免);
注意:如果需要通過形參改變外部的實參,可以優先使用引用
如果不想要通過形參改變外部的實參:a如果是內建型別,直接傳值即可;b.如果是自定義型別,傳引用並且使用const對形參進行修飾 - 指標和引用的區別
a.在底層的實現上:
引用變數實際是有自己的空間的,該空間中放置的是其引用的實體地址;實現引用的技術是指標方式來實現的
說明:引用和指標在底層的實現方式上是相同的,引用就是按照指標的方式來實現的,從底層的實現上來看,是沒有任何區別的
1.引用概念上定義一個變數的別名,指標儲存的是一個變數地址;
2.引用在定義時必須初始化,指標沒有要求;
3.引用在初始化時引用一個實體後就不能再引用其他實體;而指標可以在任何時候指向任意一個同類型實體;
4.沒有NULL引用,但有NULL指標;
5.在sizeof中含義不同,引用結果為引用型別的大小,但指標始終是地址空間所佔位元組個數(32位平臺下佔4個位元組);
6.引用自加即引用的實體增加1,指標自加即指標向後偏移一個型別的大小;
7.有多級指標,但是沒有多級引用;
8.訪問實體方式不同,指標需要顯式解引用,引用編譯器自己處理;
9.引用比指標使用起來相對更安全;
行內函數
- 概念
以inline修飾的函式叫做行內函數,編譯時C++編譯器會在呼叫行內函數的地方展開,沒有函式壓棧的開銷,行內函數提升程式執行的效率。 - 特性
a.inline是一種以空間換時間的做法,省去呼叫函式額開銷。所以程式碼很長或者有迴圈/遞迴的函式不適宜使用作為行內函數。
b.inline對於編譯器而言只是一個建議,編譯器會自動優化,如果定義為inline的函式體內有迴圈/遞迴等等,編譯器優化時會忽略掉內聯
c.inline不建議宣告和定義分離,分離會導致連結錯誤。因為inline被展開,就沒有函式地址了,連結就會找不到。 - 巨集函式和行內函數的區別
巨集函式的優點:
在預處理階段,前處理器會將巨集函式使用巨集體展開,則少了函式呼叫引數壓棧、棧幀開闢等的開銷,提高了程式的效率,一般適合比較短小功能的程式碼。
巨集函式的缺點:
a.巨集函式在預處理階段展開,不會參與編譯,無參進行引數型別檢測,不安全
b.巨集函式被展開了,不能除錯
c.有時書寫比較麻煩,需要到處加括號,否則就會出錯
d.可能會有副作用
e.多次展開,可能會引起程式碼膨脹
#define MAX(A, B) (((A) > (B))? (A) : (B))
int main()
{
int a = 10, b = 20;
cout<<MAX(++b, a)<<endl; // 期望輸出21,但實際輸出的是22,因為直接替換後,++b算了兩次
return 0;
}
行內函數可以解決大部分巨集的缺陷,而且保留了巨集的優點,因此在C++中建議使用行內函數取代巨集函式。