觀看了唐老師講解的一節《第5課 - 引用的本質分析》感覺非常不錯,有深度不廢話,我喜歡~~~ 再此總結下,並且奉上視頻下載地址~~~ 360網盤下載地址: https://yunpan.cn/cxXynI6sGbHJs 密碼(4b1b) // 正文 在C里並沒引用這個語法,而在C++里具有這個語法。 ...
觀看了唐老師講解的一節《第5課 - 引用的本質分析》感覺非常不錯,有深度不廢話,我喜歡~~~
再此總結下,並且奉上視頻下載地址~~~
360網盤下載地址: https://yunpan.cn/cxXynI6sGbHJs 密碼(4b1b)
//----------------------------------------------正文----------------------------------------------
在C里並沒引用這個語法,而在C++里具有這個語法。為什麼C++要添加引用這個語法?
我的理解就是引用就是對指針的封裝!
首先,指針變數有多種種形態:p *p &p;
1)p: 代表指針變數中存放的地址值,這個地址值一般就是某個變數的記憶體地址。
2)*p: 對應的是,p里存放的記憶體地址中的值。
3)&p: 存放指針變數的記憶體地址。
使用指針就意味著隨時,形態的轉變,如取地址,解引用。有時候理解稍微偏差,忘記取地址或者是解引用,就會出現莫名其妙的問題。
為了簡化指針的使用,並且和指針擁有一樣的強大功能,引用就出現了。
先看一段程式:
int main(int argc, char *argv[]) { //普通變數 int a0 = 8; int b0 = a0; b0 = 88; cout << a0 << endl; //指針變數 int a1 = 8; int* b1 = &a1; cout << *b1 << endl; *b1 = 88; cout << a1 << endl; //引用 int a2 = 8; int& b2 = a2; b2 = 88; cout << a2 << endl; return 0; }
1、b0為普通變數,int b0 = a0;僅僅是簡單的賦值,所以改變b0的值無法改變
a0的值,它們關聯不同的記憶體空間。
2、b1為指針變數,int* b1 = &a1;這一句將a1的地址給b1這個指針變數。
3、b2為a2的引用,int& b2 = a2;就表示b2和a2關聯上了。從此它們同氣連枝不分彼此。引用這段程式和普通變數那段程式相比解決多了一個&而已,但是卻達到了指針的效果。省去了指針解引用取地址這樣的過程。看上去就給同一塊記憶體空間取了兩個名字,這兩個名字任意一個都可以對這篇記憶體進行操作。
知道了引用的好處,再來分析他的原理,之前說過我的理解引用就是對指針的封裝,其實在引用的背後,其實就是指針,只是編譯器隱藏了這個細節。如何證明呢?
首先新建一個結構體:
struct TRef
{
char& r;
};
然後測試這個結構體的大小:
cout << sizeof(TRef) << endl;
發現大小為4,正好是一個指針的大小!(去掉&測試大小是1).進一步分析就得看彙編
Char& b = a; 反彙編之後變成了兩句:
第一句將a的地址放大eax寄存器,然後將eax的值及a的地址放到了b所在的地址空間,所以b里裝的是a的地址值。這就是指針的實現過程!
所以一旦編譯器,識別到這個變數是個引用,那麼當給這個引用關聯一個變數時,編譯器自動給被關聯的變數取地址,當給引用賦值常量的時候,編譯器自動給該變數解引用。
正因為,編譯器幫你自動完成了取地址和解引用,你才可以不用作這些容易出錯的事情,而且完成指針的工作。
這裡補充說明一點:
如果你直接去測試cout << sizeof(char&) << endl;的值大小是1,而不是4.這是因為,如果直接訪問引用,編譯器就會幫你完成解引用這個過程,那麼你檢測的就是char而不是指針了。而放到結構體裡面 就是為了不去直接操作引用 而得到引用的特性。