C++總結1——指標和引用/陣列的區別【轉】
1.指標和引有什麼區別?(從反彙編角度回答)
a.其實引用和指標本質上是一樣的,他們的彙編指令都是兩行。
int a = 10; int *p = &a; //lea eax,[a] 將a的地址放在eax暫存器中 //mov dword ptr [p], eax 將eax暫存器中的值給p
int &q = q; //lea eax,[a] 將a的地址放在eax暫存器中 //mov dword ptr [q],eax 將eax暫存器中的值給q
可以通過引用或指標解引用改變變數的值,這兩種操作產生的彙編指令也是一樣的。 *p = 20; //mov eax, dword ptr[p] 將p的值(即變數a的地址)放在eax暫存器中 //mov dword ptr[eax], 14h 將14h賦值給eax暫存器中儲存的變數 q = 20;
//mov eax,dword ptr[q] 將q的值(即變數a的地址)放在eax暫存器中 //mov dword ptr[eax],14h 將14h賦值給eax暫存器中儲存的變數
b.定義引用變數必須初始化,指標變數可以初始化。引用其實就是C++中的常量指標。表示式int &p = a;實則會被編譯器編譯為int *const p = &a;所以,引用變數必須初始化是因為const型別變數必須初始化。
c.引用變數定義時引用誰,永遠引用誰。一經引用,不能改變。指標可以更改其指向,指向別的變數。原因也是因為引用就是C++中的常量指標,常量指標的指向不能修改。
d.使用引用變數會自動解引用。在X86體系,32位平臺linux平臺上,指標佔4個位元組,如果對引用變數求sizeof,是該引用變數引用的變數所佔的位元組數。這是因為引用是一種會被編譯器自動解引用的指標。
e.C99標準中,引用只能有一級引用,指標可以有多級指標。C11標準中支援多級引用。
擴充套件部分:
你有沒有疑問:上面剛說引用變數佔用記憶體,但現在列印引用變數的地址和普通變數的地址卻是一樣的!
回顧剛才說的,引用其實就是C++中的常量指標。把上段程式碼中的引用變數都用常量指標替換,程式碼如下: 這段程式碼才是編譯器真正編譯的程式碼!
從反彙編程式碼看:
cout<<&a; //lea eax,[a] 將a的地址放在eax暫存器中 //push eax 將eax暫存器壓棧
cout<<&p; //mov eax,dword ptr[p] 將p的值(p裡儲存的是a的地址)放在eax暫存器中 //push eax 將eax暫存器壓棧
我要指出的是,C++標準並沒有解釋編譯器如何實現引用的行為。所以其實現取決於編譯器,而大多數情況下就是將其實現為一個 const 指標。
看到這兒,你應該對指標和引用的區別有了比較全面的理解了。
2.指標和陣列有什麼區別?
a.在X86體系,32位平臺上,指標佔4個位元組。陣列所佔的位元組大小與陣列型別有關。sizeof(陣列型別)*size
b.指標儲存的資料的地址,陣列儲存的是資料的值
c.使用指標是間接獲取資料,首先取得指標的內容。然後把它作為地址,從這個地址取資料。使用陣列是直接獲取資料
e.指標和陣列之間的表示可以互換
int arr[10] = {0,1,2,3,4,5,6,7,8,9}; int *p = arr;
int i = 3; p[i] = *(p+i); *(arr+i) = arr[i];