天天看點

靜态成員函數_C++:30 C++類成員,成員函數的記憶體布局

前面兩篇文章我相信大家反複讀了之後對這節不陌生了:

首先來看代碼:

class Demo{public:  //靜态成員變量  static const int sx = 0;  //靜态函數  static void SF1(){  }public:  //成員變量  int x;public:  //成員函數  void F1(){    cout << "I'm from Demo::F1()" << endl;  }  void F2(){    cout << "I'm from Demo::F1()" << endl;  }  virtual void F3(){    cout << "virtual F3()" << endl;  }public:  //構造函數,C++文法不允許擷取構造函數和析構函數位址,要分析其位址,隻能檢視生産的彙編代碼了。  Demo()  {  }  //析構函數  ~Demo()  {  }}; typedef void (Demo::*Func)(); typedef void(*func)();union{  Func f;  void *addr;}ut;int main(int argc, char** argv){  int i = 0;  cout << "main()函數的位址是       :" << std::hex << std::showbase << main << endl;  ut.f = &Demo::F1;  cout << "成員函數F1()的位址是     :" << std::hex << std::showbase << ut.addr << endl;  ut.f = &Demo::F2;  cout << "成員函數F2()的位址是     :" << std::hex << std::showbase << ut.addr << endl;  cout << "靜态成員函數SF1()的位址是:" << std::hex << std::showbase << Demo::SF1 << endl;  cout << "靜态成員變量sx的位址是   :" << std::hex << std::showbase << &Demo::sx << endl;  cout << "Demo類型執行個體的大小    :" << sizeof(Demo) << endl;  Demo* pObj = new Demo();  cout << "對象指針變量的位址是     :" << std::hex << std::showbase << &pObj << endl;  cout << "建立對象的位址是         :" << std::hex << std::showbase << pObj << endl;  cout << "成員變量的位址是         :" << std::hex << std::showbase << &pObj->x << endl;  cout << "虛函數表的入口位址     :" << std::hex << std::showbase << pObj << endl;  cout << "虛函數表F3的位址:"<< (int*)*(int*)(pObj) <<endl;     return 0;}
           

這段代碼的運作結果如下:

靜态成員函數_C++:30 C++類成員,成員函數的記憶體布局

這裡要指出的是大家可以看到靜态成員函數和靜态成員變量sx的位址都是0x00007FF開頭的,實際上他們都在全局資料區域存儲(全局變量,靜态變量),如果你有耐心,可以斷點檢視下棧空間内的局部變量i的位址:

靜态成員函數_C++:30 C++類成員,成員函數的記憶體布局

你會發現棧空間的位址和全局資料區的位址都不一樣,這樣你也了解了虛函數表的空間。

這樣看這張圖,你就知道哪些變量在哪裡存儲了。

靜态成員函數_C++:30 C++類成員,成員函數的記憶體布局

如果我們修改對象構造的方式,通過在棧上構造一個對象,

int main(int argc, char** argv){   Demo pObj;   cout << "建立對象的位址是         :" << std::hex << std::showbase << &pObj << endl;  cout << "成員變量的位址是         :" << std::hex << std::showbase << &pObj.x << endl;  cout << "靜态成員函數SF1()的位址是:" << std::hex << std::showbase << Demo::SF1 << endl;  cout << "靜态成員變量sx的位址是   :" << std::hex << std::showbase << &Demo::sx << endl;  ut.f = &Demo::F1;  cout << "成員函數F1()的位址是     :" << std::hex << std::showbase << ut.addr << endl;  ut.f = &Demo::F2;  cout << "成員函數F2()的位址是     :" << std::hex << std::showbase << ut.addr << endl;  cout << "虛函數表的入口位址     :" << std::hex << std::showbase << &pObj << endl;  cout << "虛函數表F3的位址:"<< (int*)*(int*)(&pObj) <<endl;     return 0;}
           
靜态成員函數_C++:30 C++類成員,成員函數的記憶體布局

我想你現在根據剛才列印的成員變量,成員函數,虛函數表位址已經可以自己畫出類成員的記憶體布局了。

繼續閱讀