1. 程式人生 > >C++——類例項化記憶體的分配和this指標的使用

C++——類例項化記憶體的分配和this指標的使用

一、類的例項化分配記憶體

類是結構體的演變,是一種資料型別,如int和char一樣是型別。那麼在類例項化時,記憶體是怎樣分配的呢?

步驟是:(可以通過程式碼考證)

1.屬性、方法不需要初始化,因為這些全部是指標。
2.初始化派生類的靜態欄位。
3.初始化派生類的非靜態欄位。
4.初始化基類的靜態欄位。
5.初始化基類的非靜態欄位。
6.呼叫基類的建構函式。
7.呼叫派生類的建構函式。

 類分為成員變數和成員函式,我們先來討論成員變數。

 一個類物件的地址就是類所包含的這一片記憶體空間的首地址,這個首地址也就對應具體某一個成員變數的地址。(在定義類物件的同時這些成員變數也就被定義了)我們來以一段程式碼說明問題: 

//類的定義

class K{
public:
 K(){k = 12;}
 ~K(){}
 int k;
}; 

//類的使用

//... K kTemp;

 printf("%d--%d\n",&kTemp,&kTemp.k);
 printf("%d--%d\n",sizeof(K),sizeof(kTemp.k));
 int *i = (int*)(&kTemp);
 int w = *i;
 printf("%d\n",w); 執行上面的程式碼,

結果如下:

1310588--1310588
4--4
12

很明顯,類的記憶體大小和其唯一的成員變數的記憶體大小是一致的。記憶體地址也是一致的。他們甚至可以相互轉換。換成結構體結果也是一樣。網友可以自己執行上面程式碼來進行確認。 這個時候,可能有人會提出疑問了。那麼成員函式又如何
?上面得程式碼就好像類沒有任何成員函式一樣,根本說明不了問題。 呵呵,所有的函式都是存放在程式碼區的, 不管是全域性函式,還是成員函式。要是成員函式佔用類的物件空間,那麼將是多麼可怕的事情:定義一次類物件就有成員函式佔用一段空間。 我們再來補充一下靜 態成員函式的存放問題吧:靜態成員函式與一般成員函式的唯一區別就是沒有this指標,因此不能訪問非靜態資料成員,就像我前面提到的,所有函式都存放在程式碼區,靜態函式也不例外。所有有人一看到 static 這個單詞就主觀的認為是存放在全域性資料區,那是不對的.

當K kTemp 時,(new k()有待考證)就真正在Heap中例項化了一個物件,這個時候也將Heap上的地址寫入了K在Stack中的記憶體地址。K有了Reference,且指向了其在Heap中的物件。


例項化Heap中的物件時,簡單的成員變數(貌似還有屬性等)一樣是繼續在Stack上隨例項單獨分配記憶體地址。而類中的方法則是由物件們共享的。

二、this的使用

1.this在成員函式的開始前構造,在成員的結束後清除。
這個生命週期同任何一個函式的引數是一樣的,沒有任何區別。
因為,成員函式預設第一個引數就是this。
舉例:
class   A{
        public:
                int   func(int   p){}
};
func的原型在編譯器看來,應該是
int   func(A*   const   this,   int   p);

即開始執行成員函式之前,構造。
成員函式執行結束,清除。

2.this指標的的存放位置

(1)this指標的存放位置和編譯器相關,可能是棧,暫存器,全域性變數區

3.this指標的是如何傳遞給類中函式的

 (1)大多數編譯器通過eax暫存器傳遞this指標。在呼叫之前,編譯器會把對應的物件地址放在eax暫存器中

4.我們取得一個物件時,可以獲取其this指標。如果知道一個物件this指標的位置,能夠直接使用嗎?

(1)this指標只有在成員函式中才有定義。只有在成員函式中,是可以通過&this獲得地址的,也可以直接使用它。

(2)如果獲得一個物件,也不能通過物件使用this指標。

5.每個類編譯後,是否會產生一個類中函式表來儲存函式指標?

普通的函式(成員函式,靜態函式)都不會產生一個函式表,只有虛擬函式才會被放入函式表。

即使是虛擬函式,當編譯器明確呼叫哪個函式時,也會直接呼叫,不會通過函式表的指標呼叫。

6.this指標的作用域

this指標只在非靜態函式中存在,所以靜態函式不能使用this指標為非靜態變數賦值。[待考證]

http://blog.sina.com.cn/s/blog_725dd1010100u12f.html這篇文章的最後有講解繼承的一些概念,以後學習。另外EAX的暫存器是什麼?