1. 程式人生 > >反彙編C++ OOP程式碼 分析建構函式如何被呼叫 以及簡單的C++物件記憶體模型

反彙編C++ OOP程式碼 分析建構函式如何被呼叫 以及簡單的C++物件記憶體模型

在今天進行C++程式碼的思考時,產生一個疑問,就是C++類的建構函式是如何被呼叫的

於是就做了一個簡單的實驗來驗證自己的想法。

//main.cpp
#include <stdio.h>

class People{
private:
int i;
int b;
public:
People(int i){
  this->i = i;
  printf("This OOP addr is %p\n", this);
}

};

int main(){

int n = 20;
People i(30);
People y(20);

return
0; }

然後我們將該程式碼進行反彙編,得到Mian函式的彙編程式碼如下

00AE1460 push ebp
00AE1461 mov ebp,esp
**00AE1463 sub esp,0F0h**
00AE1469 push ebx
00AE146A push esi
00AE146B push edi
00AE146C lea edi,[ebp-0F0h]
00AE1472 mov ecx,3Ch
00AE1477 mov eax,0CCCCCCCCh
00AE147C rep stos dword ptr es:[edi]
00AE147E mov eax,dword ptr ds:[00AE9000h]
00AE1483 xor eax,ebp
00
AE1485 mov dword ptr [ebp-4],eax int n = 20; 00AE1488 mov dword ptr [n],14h People i(30); **00AE148F push 1Eh 00AE1491 lea ecx,[i] 00AE1494 call People::People (0AE10EBh)** ;從這裡我們可以知道,建構函式的呼叫是在編譯階段實現的。 People y(20); 00AE1499 push
14h 00AE149B lea ecx,[y] 00AE149E call People::People (0AE10EBh) return 0; 00AE14A3 xor eax,eax }

 

 

 

分析上面的程式碼,我們可以知道,
main函式一開始,首先進行的是一些通用的彙編模板,然後就是在棧中開闢了一個大小0xF0h的空間,
我們可以想到,這些空間就是用來存放區域性變數的,而我們定義的兩個物件也將存放在棧裡面。
如果我們是用 new 來例項化物件的話,那麼物件將不會被放在棧裡面,而是放在了堆裡面。

00AE148F push 1Eh
00AE1491 lea ecx,[i]                                                                      
00AE1494 call People::People (0AE10EBh)

從這三行程式碼,我們可以獲得的資訊有:

  • 建構函式的概念是在編譯階段是實現的
  • 實際傳遞給建構函式的引數有兩個,一個就是我們定義的整形,一個就是名不見經傳的this 也就是物件的地址
接下來我們去分析 People的彙編程式碼,就可以知道我們的分析是沒有錯的。在這裡呢,我就偷懶不去分析多一次了。

最後總結一下:

C++的面向物件的思想和實現是在編譯階段實現的。
我們將他編譯完之後,在執行階段和C語言無區別。

C++類中函式,我推測它是存在於某個段中,而他的成員變數是存在於棧中或者是堆中。


本文為原創文章,轉載請註明出處 Atqiao或 ***大呆書生***