1.指針就是數據或代碼在內存中的地址,指針變量指向的就是內存中的數據或代碼。這里有一個關鍵詞需要強調,就是內存,指針只能指向內存,不能指向寄存器或者硬盤,因為寄存器和硬盤沒法尋址。
2.其實 C++ 代碼中的大部分內容都是放在內存中的,例如定義的變量、創建的對象、字符串常量、函數形參、函數體本身、new或malloc()分配的內存等,這些內容都可以用&來獲取地址,進而用指針指向它們。除此之外,還有一些我們平時不太留意的臨時數據,例如表達式的結果、函數的返回值等,它們可能會放在內存中,也可能會放在寄存器中。一旦它們被放到了寄存器中,就沒法用&獲取它們的地址了,也就沒法用指針指向它們了。
3.寄存器離 CPU 近,并且速度比內存快,將臨時數據放到寄存器是為了加快程序運行。但是寄存器的數量是非常有限的,容納不下較大的數據,所以只能將較小的臨時數據放在寄存器中。int、double、bool、char 等基本類型的數據往往不超過 8 個字節,用一兩個寄存器就能存儲,所以這些類型的臨時數據通常會放到寄存器中;而對象、結構體變量是自定義類型的數據,大小不可預測,所以這些類型的臨時數據通常會放到內存中。
4.常量表達式由于不包含變量,沒有不穩定因素,所以在編譯階段就能求值。編譯器不會分配單獨的內存來存儲常量表達式的值,而是將常量表達式的值和代碼合并到一起,放到虛擬地址空間中的代碼區。從匯編的角度看,常量表達式的值就是一個立即數,會被“硬編碼”到指令中,不能尋址。
5.引用和指針在本質上是一樣的,引用僅僅是對指針進行了簡單的封裝。引用和指針都不能綁定到無法尋址的臨時數據,并且 C++ 對引用的要求更加嚴格,在某些編譯器下甚至連放在內存中的臨時數據都不能指代。
著重看下這里
6. 引用 與 const組合在一起,類似 const int &r1,就變成了常引用
將常引用綁定到臨時數據時,編譯器采取了一種妥協機制:編譯器會為臨時數據創建一個新的、無名的臨時變量,并將臨時數據放入該臨時變量中,然后再將引用綁定到該臨時變量。注意,臨時變量也是變量,所有的變量都會被分配內存。
7.編譯器禁止指針指向不同類型的數據
引用(Reference)和指針(Pointer)在本質上是一樣的,引用僅僅是對指針進行了簡單的封裝,「類型嚴格一致」這條規則同樣也適用于引用。
7. const 引用與類型轉換
當對引用添加 const 限定后,情況就又發生了變化,編譯器允許引用綁定到類型不一致的數據,當引用的類型和數據的類型不一致時,如果它們的類型是相近的,并且遵守「數據類型的自動轉換」規則,那么編譯器就會創建一個臨時變量,并將數據賦值給這個臨時變量(這時候會發生自動類型轉換),然后再將引用綁定到這個臨時的變量,這與「將 const 引用綁定到臨時數據時」采用的方案是一樣的。
8.
給引用添加 const 限定后,不但可以將引用綁定到臨時數據,還可以將引用綁定到類型相近的數據,這使得引用更加靈活和通用,它們背后的機制都是臨時變量。
引用類型的函數形參請盡可能的使用 const
使用 const 可以避免無意中修改數據的編程錯誤;
使用 const 能讓函數接收 const 和非 const 類型的實參,否則將只能接收非 const 類型的實參;
使用 const 引用能夠讓函數正確生成并使用臨時變量。