反彙編C++ OOP程式碼 分析建構函式如何被呼叫 以及簡單的C++物件記憶體模型
阿新 • • 發佈:2018-12-07
在今天進行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 也就是物件的地址
最後總結一下:
C++的面向物件的思想和實現是在編譯階段實現的。
我們將他編譯完之後,在執行階段和C語言無區別。
C++類中函式,我推測它是存在於某個段中,而他的成員變數是存在於棧中或者是堆中。
本文為原創文章,轉載請註明出處 Atqiao或 ***大呆書生***