大家對C++的引用應該都不陌生吧,抱著既要知其然,也要知其所以然的態度。下面將按照是什麼?怎麼用?為什麼需要?本質剖析的流程來向大家一一描述。
引用是什麼?
引用其實就是給變數起的一個別名,使用這個別名跟使用變數名沒有區別。
那什麼又是變數名呢?
變數名實質上是一段連續儲存空間的別名,是一個標號(門牌號),編譯器通過變數來申請並命名記憶體空間,程式設計師可以通過變數的名字可以使用儲存空間。
也可以這樣理解,變數名是邏輯概念,變數是物理層面,變數含資料型別和資料值,資料型別決定記憶體的分配,編譯器將變數名和變數對應的記憶體聯絡起來,使程式設計師可以通過變數名來操作記憶體。
引用怎麼用?
語法:Type& name = var;
規則:1、普通引用在宣告時必須用其它的變數進行初始化
2、引用作為函式引數宣告時不進行初始化(後面將通過引用本質來解釋原因)
為什麼需要引用?
1)引用作為其它變數的別名而存在,因此在一些場合可以代替指標
2)引用相對於指標來說具有更好的可讀性和實用性
引用為java等高階的語言程式設計師提供了很大便利,其不需要了解C++中的指標,只需要按照以前的習慣來使用就可以。
引用的本質剖析(很重要!!)
1、引用其實是個常量,證明如下
1 2 3 4 5 6 |
int main() { int a = 1; //int& b; C++編譯器提示:錯誤“b”,必須初始化引用-->說明引用是個常量 int& b = a; } |
說明: 必須初始化引用–>說明引用是個常量
2、引用其實也是個指標,證明如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
struct teacher { int age; //4個位元組 teacher& m_techer; }; struct student { int age; //4個位元組 short& weight; }; int main() { cout說明m_techer的 引用佔4個位元組*/ cout說明weight的引 用佔4個位元組*/ system("pause"); return 0; } |
說明:從上面teacher&和short&的兩個引用中佔用的4個位元組(32位系統),可以推斷出引用其實是個指標。
根據1、2的結論可以推斷出引用其實是個指標常量或者是常量指標,下面進一步證明。
3、引用其實是個指標常量 ,證明如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int main() { int a =10; int m = 22; int& b = a; &b = &m; /*疑問: b是引用,引用是個指標,指標賦值為什麼還要在取地址符&b (因為編譯器在我們使用引用時,自動給引用披上了間接引用的外衣即:*b) 編譯錯誤 “=”: 左運算元必須為左值-->引用是個指標常量,不能修改 其指標的指向。*/ system("pause"); return 0; } |
說明:引用是個指標常量。下面會說出C++編譯器是怎麼在C語言的基礎上加入引用機制的。
4、C++編譯器在C語言的基礎上加入引用機制
說明:
1、宣告引用時,C語言將引用宣告的是指標常量。(為啥要初始化引用原因)
2、引用使用,C語言隱藏了對常指標自動間接引用,讓我們完全不用瞭解指標
3、初始化引用時,C語言隱藏了對變數的取地址符&操作,讓我們感覺是在直接給變數起別名
應用的剖析到此就結束了,下面我們來說說匿名物件吧。
什麼是匿名物件
匿名物件可以理解為是一個臨時物件,一般系統自動生成的,如你的函式返回一個物件,這個物件在返回時會生成一個臨時物件。
匿名物件的生命週期(很重要!!!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
class Cat { public: Cat() { cout<<"Cat類 無參建構函式"<<endl; } Cat(Cat& obj) { cout<<"Cat類 拷貝建構函式"<<endl; } ~Cat() { cout<<"Cat類 解構函式 "<<endl; } }; void playStage() //一個舞臺,展示物件的生命週期 { Cat(); /*在執行此程式碼時,利用無參建構函式生成了一個匿名Cat類物件;執行完此行程式碼, 因為外部沒有接此匿名物件的變數,此匿名又被析構了*/ Cat cc = Cat(); /*在執行此程式碼時,利用無參建構函式生成了一個匿名Cat類物件;然後將此匿名變 成了cc這個例項物件,此匿名物件沒有被析構。*/ cout<<"cc 物件好沒有被析構"<<endl; } int main() { playStage(); system("pause"); return 0; } |
輸出:
1 2 3 4 5 |
Cat類 無參建構函式 Cat類 解構函式 Cat類 無參建構函式 cc 物件好沒有被析構 Cat類 解構函式 |
說明:
1、在執行playStage( )函式中的Cat( )時,生成了一個匿名物件,執行完Cat( )程式碼後,此匿名物件就此消失。這就是匿名物件的生命週期。
2、在執行playStage( )函式中Cat cc = Cat();時,首先生成了一個匿名物件,因為外部有cc物件在等待被例項化,然後將此匿名物件變為了cc物件,其生命週期就變成了cc物件的生命週期。
總結:
如果生成的匿名物件在外部有物件等待被其例項化,此匿名物件的生命週期就變成了外部物件的生命週期;如果生成的匿名物件在外面沒有物件等待被其例項化,此匿名物件將會生成之後,立馬被析構。
最後希望能對大家有幫助,沙米才疏學淺,有什麼錯誤請留言指正,謝謝大家。