C 成員函式在記憶體中的儲存方式

2021-09-26 14:36:00 字數 1513 閱讀 7123

用類去定義物件時,系統會為每乙個物件分配儲存空間。如果乙個類包括了資料和函式,要分別為資料和函式的**分配儲存空間。按理說,如果用同乙個類定義了10個物件,那麼就需要分別為10個物件的資料和函式**分配儲存單元,如下圖所示。

能否只用一段空間來存放這個共同的函式**段,在呼叫各物件的函式時,都去呼叫這個公用的函式**。如下圖所示。

顯然,這樣做會大大節約儲存空間。c++編譯系統正是這樣做的,因此每個物件所占用的儲存空間只是該物件的資料部分(虛函式指標和虛基類指標也屬於資料部分)所占用的儲存空間,而不包括函式**所占用的儲存空間。

看如下測試**:

class d  

問題:以上**的輸出結果是什麼?

c++程式的記憶體格局通常分為四個區:全域性資料區(data area),**區(code area),棧區(stack area),堆區(heap area)(即自由儲存區)。全域性資料區存放全域性變數,靜態資料和常量;所有類成員函式和非成員函式**存放在**區;為執行函式而分配的區域性變數、函式引數、返回資料、返回位址等存放在棧區;餘下的空間都被稱為堆區。根據這個解釋,我們可以得知在類的定義時,類成員函式是被放在**區,而類的靜態成員變數在類定義時就已經在全域性資料區分配了記憶體,因而它是屬於類的。對於非靜態成員變數,我們是在類的例項化過程中(構造物件)才在棧區或者堆區為其分配記憶體,是為每個物件生成乙個拷貝,所以它是屬於物件的。

應當說明,常說的「某某物件的成員函式」,是從邏輯的角度而言的,而成員函式的儲存方式,是從物理的角度而言的,二者是不矛盾的。

下面我們再來討論下類的靜態成員函式和非靜態成員函式的區別:靜態成員函式和非靜態成員函式都是在類的定義時放在記憶體的**區的,因而可以說它們都是屬於類的,但是類為什麼只能直接呼叫靜態類成員函式,而非靜態類成員函式(即使函式沒有引數)只有類物件才能呼叫呢?原因是類的非靜態類成員函式其實都內含了乙個指向類物件的指標型引數(即this指標),因而只有類物件才能呼叫(此時this指標有實值)。

回答開頭的問題,答案是輸出「printa」後,程式崩潰。類中包括成員變數和成員函式。new出來的只是成員變數,成員函式始終存在,所以如果成員函式未使用任何成員變數的話,不管是不是static的,都能正常工作。需要注意的是,雖然呼叫不同物件的成員函式時都是執行同一段函式**,但是執行結果一般是不相同的。不同的物件使用的是同乙個函式**段,它怎麼能夠分別對不同物件中的資料進行操作呢?原來c++為此專門設立了乙個名為this的指標,用來指向不同的物件。

需要說明,不論成員函式在類內定義還是在類外定義,成員函式的**段都用同一種方式儲存。不要將成員函式的這種儲存方式和inline(內聯)函式的概念混淆。不要誤以為用inline宣告(或缺省為inline)的成員函式,其**段占用物件的儲存空間,而不用inline宣告的成員函式,其**段不占用物件的儲存空間。不論是否用inline宣告(或缺省為inline),成員函式的**段都不占用物件的儲存空間。用inline宣告的作用是在呼叫該函式時,將函式的**段複製插人到函式呼叫點,而若不用inline宣告,在呼叫該函式時,流程轉去函式**段的入口位址,在執行完該函式**段後,流程返回函式呼叫點。inline與成員函式是否占用物件的儲存空間無關,它們不屬於同乙個問題,不應搞混。

C 成員函式在記憶體中的儲存方式

用類去定義物件時,系統會為每乙個物件分配儲存空間。如果乙個類包括了資料和函式,要分別為資料和函式的 分配儲存空間。按理說,如果用同乙個類定義了10個物件,那麼就需要分別為10個物件的資料和函式 分配儲存單元,如下圖所示。能否只用一段空間來存放這個共同的函式 段,在呼叫各物件的函式時,都去呼叫這個公用...

C 成員函式在記憶體中的儲存方式

用類去定義物件時,系統會為每乙個物件分配儲存空間。如果乙個類包括了資料和函式,要分別為資料和函式的 分配儲存空間。按理說,如果用同乙個類定義了10個物件,那麼就需要分別為10個物件的資料和函式 分配儲存單元,如下圖所示。能否只用一段空間來存放這個共同的函式 段,在呼叫各物件的函式時,都去呼叫這個公用...

C 類成員在記憶體中的儲存及對齊方式

一 空類的大小 c 中空類的大小是1,這是因為空類也可以被例項化,為了確保每乙個例項在記憶體中都有乙個獨一無二的位址,編譯器往往隱含給乙個空類加乙個位元組。二 類中的成員函式與非虛成員函式 類中的非虛成員函式不占用空間,虛函式表占用四個位元組,只要有虛函式 無論有幾個 都只占用四個位元組。成員函式還...