引用的條件及從彙編角度理解引用

2021-08-20 02:08:33 字數 2973 閱讀 1325

引用:引用可以看作是對已定義變數的別名,變數名實際上是對一段連續儲存空間的別名。

關於引用幾點比較重要的內容:

(1)定義引用時必須進行初始化。

(2)初始化的值要能取位址,不能用乙個立即數進行初始化。

int &p = 100;//這是錯誤的
(3)引用不能改變,一旦初始化,不能引用其他變數名。

(4)訪問引用變數,永遠訪問的是被引用變數的記憶體。

引用的這幾點重要的內容,可以反應出引用相對於指標來講,更加安全。她不會引用乙個未初始化的記憶體塊,建議在c++中更多使用引用。

提出乙個問題,引用究竟有沒有進行記憶體的開闢?許多書籍上寫出引用沒有開闢空間,到底對不對呢,還是理解的方向不正確?

下面通過一段**分析

由上圖看出,修改引用和修改指標都達到修改a記憶體塊值的目的。也就是說a b *p似乎是一塊記憶體。

試著輸出一下int a = 10;int &b = a;int *p = &a;中a和b的位址,以及p的值。

對比上邊3,4,5和6,7,8彙編**,我們發現在底層語言中,壓根就沒有引用和指標的區別。

在函式棧幀的開闢中,用棧底指標ebp的偏移量表示區域性變數的位址。[ebp-4]對應的記憶體塊就是a。

int &b = a;

lea eax,[ebp-4]//就是將記憶體塊a的位址儲存在eax暫存器中

//lea指令是移位址指令,對比下邊int *p = &a的彙編指令是一摸一樣.

dword ptr [ebp-8],eax//[ebp-8]即是引用b的記憶體塊

//所以說引用是開闢了記憶體塊的,用來儲存被引用變數的位址。

int *p = &a;

lea ecx,[ebp-4]//就是將記憶體塊a的位址儲存在eax暫存器中

//lea指令是移位址指令

mov dword ptr [ebp-0ch],ecx

但是,為什麼我們輸出引用變數b的位址,卻是記憶體塊a的位址呢?

實際上,只要一旦使用,在編譯器內部就會自動進行解應用。也就是說永遠不可能訪問到引用變數b的位址,因為每當你使用引用時,已經經過解引用。

初學者如何方便的定義引用變數呢?

通過上邊的分析,引用底層也是乙個指標。只是在使用時,就進行了解引用,對程式設計師來講這個過程是透明的。

int a=10;

int *p = &a;//首先定義乙個指標

//將右邊的取位址符&覆蓋左邊的*符號,即可得到引用變數的定義

int &p = a;

定義引用變數引用陣列名

//按照上邊的規則

int arr[10] = ;

//首先定義乙個指向陣列的指標

int (*p)[10] = &arr;

//將右邊的取位址符&覆蓋左邊的*符號,即可得到引用變數的定義

64bit編譯器下,指標變數的大小為8個位元組。

引用變數作為函式引數

當陣列名作為函式引數時會退化為指標,因此實際應用中往往還需要傳遞陣列的長度。

void fun(int arr)

int main();

printf("sizeof(arr)=%d\n",sizeof(arr));

fun(arr);

}

注:64bit編譯器指標變數的大小為8個位元組。

引用作為函式引數

可見當引用變數引用陣列名時,作為函式引數不會退化為指標。

從彙編角度看引用

引用型別到底是什麼?它和指標有什麼關係?它本身占用記憶體空間嗎?帶著這些疑問,我們來進行分析。先看 include include using namespace std void main 通過彙編檢視 如下 9 int x 1 00401048 mov dword ptr ebp 4 1 10 ...

從彙編的角度看C 裡的引用和指標

c 裡有引用和指標,使用過c 的應該都知道它們的異同點。本文將從彙編的角度去觀察這2者的本質。使用也非常簡單,在左側編寫c 在右側就會直接顯示對應的組合語言,也可以根據需要的平台來選擇對應的編譯器 我們使用的c 如下,比較簡單 int main void 選擇的編譯器是x86 64 gcc 9.2,...

彙編角度看指標和引用的區別

一 定義上來看 引用是變數的別名,指標是指向變數的位址。引用不可以為空但是指標可以為空,所以引用必須在定義的時候必須初始化並且初始化後不能被改變引用的物件,但是指標可以該變自己的指向。引用必須引用有記憶體位址的量,如果是引用常量的話,必須使用常引用。常引用的實現方法是編譯器為常量開闢乙個臨時量的記憶...