從匯編看c++中引用與指針的使用分析
首先是引用情形下的c++源碼:
void add(int a, int b, int&c) {
c = a + b;
}
int main() {
int a = 1;
int b = 2;
int c = 0;
add(a, b, c);
}
下面是main對(duì)應(yīng)的匯編碼:
; 6 : int main() {
push ebp
mov ebp, esp
sub esp, 12 ; 為該調(diào)用函數(shù)的??臻g預(yù)留12byte,用來存儲(chǔ)局部變量a,b, c
; 7 : int a = 1;
mov DWORD PTR _a$[ebp], 1;初始化a _a$為a存儲(chǔ)空間地址相對(duì)于ebp基址的偏移量
; 8 : int b = 2;
mov DWORD PTR _b$[ebp], 2;初始化b _b$為b存儲(chǔ)空間地址相對(duì)于ebp基址的偏移量
; 9 : int c = 0;
mov DWORD PTR _c$[ebp], 0;初試化c _c$為c存儲(chǔ)空間地址相對(duì)于ebp基址的偏移量
; 10 : add(a, b, c);
lea eax, DWORD PTR _c$[ebp]; 獲取c存儲(chǔ)空間相對(duì)于ebp基址的偏移量(即c存儲(chǔ)單元的偏移地址),放在寄存器eax中
push eax;保存c存儲(chǔ)空間的偏移量到堆棧中
mov ecx, DWORD PTR _b$[ebp];將b存儲(chǔ)空間里面的值(即b的值)放在寄存器ecx中
push ecx;保存b存儲(chǔ)空間的值到堆棧中
mov edx, DWORD PTR _a$[ebp];將a存儲(chǔ)空間里面的值(即a的值)放在寄存器edx里面
push edx;保存a存儲(chǔ)空間的到堆棧
;上面push eax push ecx push edx在棧里面存儲(chǔ)了原來局部變量a,b,c的值,只不過對(duì)于c來說,存儲(chǔ)的是c存儲(chǔ)空間的偏移地址
;因此,對(duì)于a,b來說,也就是將他們的值得一份拷貝存了起來,也就是傳值;而c只是存儲(chǔ)了自己存儲(chǔ)空間的偏移地址,也就是傳地址
call ?add@@YAXHHAAH@Z ; 調(diào)用add函數(shù),上面的語句已經(jīng)為傳遞參數(shù)做好了準(zhǔn)備
add esp, 12 ; 由于剛才為調(diào)用函數(shù)add傳遞參數(shù)進(jìn)行了壓棧,這里釋放??臻g,即釋放參數(shù)
;這就是為什么函數(shù)調(diào)用完成后局部變量和參數(shù)無效的原因,因?yàn)樗麄兊目臻g被釋放了
; 11 :
; 12 : }
xor eax, eax
mov esp, ebp
pop ebp
ret 0
下面是函數(shù)add對(duì)應(yīng)的匯編碼:
; 1 : void add(int a, int b, int&c) {
push ebp
mov ebp, esp
; 2 : c = a + b;
mov eax, DWORD PTR _a$[ebp];取參數(shù)a的值到寄存器eax中
add eax, DWORD PTR _b$[ebp];取參數(shù)b的值與eax中a的值相加,結(jié)果放到eax中
mov ecx, DWORD PTR _c$[ebp];去c的偏移地址放到寄存器ecx中
mov DWORD PTR [ecx], eax;將eax中的結(jié)果寫到由ecx指定的地址單元中去,即c所在存儲(chǔ)單元
; 3 : }
pop ebp
ret 0
從上面可以看到,對(duì)于傳值,c++確實(shí)傳的是一份值拷貝,而對(duì)于引用,雖然是傳值的形式,但是其實(shí)編譯器內(nèi)部傳遞的是值得地址
下面是指針的情形的c++源碼:
void add(int a, int b, int* c) {
*c = a + b;
}
int main() {
int a = 1;
int b = 2;
int c = 0;
add(a, b, &c);
}
mian函數(shù)對(duì)應(yīng)的匯編碼:
; 6 : int main() {
push ebp
mov ebp, esp
sub esp, 12 ;
; 7 : int a = 1;
mov DWORD PTR _a$[ebp], 1
; 8 : int b = 2;
mov DWORD PTR _b$[ebp], 2
; 9 : int c = 0;
mov DWORD PTR _c$[ebp], 0
; 10 : add(a, b, &c);
lea eax, DWORD PTR _c$[ebp]
push eax
mov ecx, DWORD PTR _b$[ebp]
push ecx
mov edx, DWORD PTR _a$[ebp]
push edx
call ?add@@YAXHHPAH@Z ; add
add esp, 12 ;
; 11 :
; 12 : }
xor eax, eax
mov esp, ebp
pop ebp
ret 0
add函數(shù)對(duì)應(yīng)的匯編碼:
; 1 : void add(int a, int b, int* c) {
push ebp
mov ebp, esp
; 2 : *c = a + b;
mov eax, DWORD PTR _a$[ebp]
add eax, DWORD PTR _b$[ebp]
mov ecx, DWORD PTR _c$[ebp]
mov DWORD PTR [ecx], eax
; 3 : }
pop ebp
ret 0
可以看到,指針和引用的匯編碼一樣,因此兩者的作用也一樣
相關(guān)文章
C++詳解默認(rèn)參數(shù)的構(gòu)造函數(shù)及簡(jiǎn)單實(shí)例代碼
這篇文章主要介紹了 C++詳解默認(rèn)參數(shù)的構(gòu)造函數(shù)及簡(jiǎn)單實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02