用彙編的眼光看C (之拷貝 賦值函式)

2021-06-02 01:52:59 字數 2541 閱讀 8544

**:

拷貝建構函式和複製函式是類裡面比較重要的兩個函式。兩者有什麼區別呢?其實也很簡單,我們可以舉個例子,加入有這樣乙個類的定義:

view plain

class

);}  

); return

*this

;}  

);}  

void

print() 

const

};  

那麼我們在如下的函式裡面進行呼叫的時候,呼叫的函式分別是哪些呢?

view plain

void

process()    

其實彙編的結果是這樣的,大家可以一起看一下,自己嘗試讀一下。如果一次不是很明白,可以多讀幾次。

view plain

0040127d   lea         ecx,[ebp-10h]  

00401285   mov         dword ptr [ebp-4],0  

0040128c   lea         ecx,[ebp-14h]  

00401294   mov         byte ptr [ebp-4],1  

00401298   lea         eax,[ebp-10h]  

0040129b   push        eax  

0040129c   lea         ecx,[ebp-18h]  

004012a4   mov         byte ptr [ebp-4],2  

72:       c = b;  

004012a8   lea         ecx,[ebp-18h]  

004012ab   push        ecx  

004012ac   lea         ecx,[ebp-14h]  

73:   }  

004012b4   mov         byte ptr [ebp-4],1  

004012b8   lea         ecx,[ebp-18h]  

004012c0   mov         byte ptr [ebp-4],0  

004012c4   lea         ecx,[ebp-14h]  

004012cc   mov         dword ptr [ebp-4],0ffffffffh  

004012d3   lea         ecx,[ebp-10h]  

004012db   mov         ecx,dword ptr [ebp-0ch]  

004012de   mov         dword ptr fs:[0],ecx  

004012e5   pop         edi  

004012e6   pop         esi  

004012e7   pop         ebx  

004012e8   add         esp,58h  

004012eb   cmp         ebp,esp  

004012ed   call        __chkesp (004087c0)  

004012f2   mov         esp,ebp  

004012f4   pop         ebp  

004012f5   ret  

(個人不同意這種說法 ,vc下就算是定義兩個字元變數堆疊也是做類似分配,如:

3:        char a='a';

00401028 mov byte ptr [ebp-4],61h

4: char b='b';

0040102c mov byte ptr [ebp-8],62h

by orc)

,就是一塊存放資料的普通記憶體。而建構函式之所以能和對應的記憶體繫結在一起,主要是因為ecx記錄了記憶體的起始位址,這在c++編譯中是十分關鍵的。我們看到的c++建構函式好像是沒有繫結記憶體,實際上在vc裡面已經做好了約定,ecx就是this指標,就是類的記憶體起始位址。有興趣的同學看看g++編譯的時候,採用的this指標是哪個暫存器儲存的?(其實是eax)

(2)71句:通過對應看到了eax記錄了引用變數的位址(並存放在堆疊中 by orc),而ecx是ebp下面緊挨著四個位元組。但是函式呼叫的位址和前面的預設建構函式不太一樣,所以我們大膽猜測,這裡的建構函式這是拷貝建構函式,我們可以在除錯的時候檢視一下列印訊息。

(3)72句:0x4012af語句已經清楚地告訴了我們,這裡呼叫的函式就是operator=函式,這一部分是算術符過載的內容,我們在後面的部落格會重點介紹。

(4)73句: 前面我們講過,析構函式在函式呼叫結束的時候被被自動呼叫,那麼這裡我們看到卻是出現了三個呼叫?這三個變數正好是我們之前說的a、b、c三個變數。那麼這三個變數呼叫的次序是怎樣的呢?我們可以檢視一下變數的位址,分別是【ebp-18h】、【ebp-14h】、【ebp-10h】,這正好和變數出現的順序相反。所以我們看到,析構函式和建構函式是嚴格一一對應的,誰先出現,誰後析構。

用彙編的眼光看C (之拷貝 賦值函式)

拷貝建構函式和複製函式是類裡面比較重要的兩個函式。兩者有什麼區別呢?其實也很簡單,我們可以舉個例子,加入有這樣乙個類的定義 那麼我們在如下的函式裡面進行呼叫的時候,呼叫的函式分別是哪些呢?void process 其實彙編的結果是這樣的,大家可以一起看一下,自己嘗試讀一下。如果一次不是很明白,可以多...

用彙編的眼光看C (之拷貝 賦值函式)

拷貝建構函式和複製函式是類裡面比較重要的兩個函式。兩者有什麼區別呢?其實也很簡單,我們可以舉個例子,加入有這樣乙個類的定義 cpp view plain copy class return this void print const 那麼我們在如下的函式裡面進行呼叫的時候,呼叫的函式分別是哪些呢?c...

用彙編的眼光看C (之特殊函式)

這裡說的函式主要指的是inline函式 static函式。inline函式比較特殊,它既具有巨集的性質,同時也能讓編譯器對它進行函式檢查。static函式同樣也比較特殊,它只可以被同檔案的函式使用。如果static函式在include檔案中,那麼這個標頭檔案只要被使用一次,那麼這個函式就要在exec...