c 程式的記憶體布局及類的大小討論

2021-08-20 19:48:43 字數 2216 閱讀 1383

1.在c++中,我們了解乙個資料型別在記憶體中所佔的記憶體大小一般都是使用sizeof函式,他可以計算基本資料型別在記憶體所佔的位元組數。當然,對於復合的資料型別也是可以的。比如說c++中最典型的資料型別:類。使用sizeof函式也是可以返回該類所占用的空間大小。當然,類的大小和基本的資料型別的大小時有區別的,也並非是類中所有資料型別大小的簡單相加。它遵循一定的規律。今天我們就來討論一下這個問題。

2.首先我們需要了解一下c++程式的記憶體布局。乙個c++檔案·經過編譯之後在記憶體中大致可以分為以下幾個區域:

(1)程式**區:該區存放這個程式中函式的二進位制**。

(2)棧區(stack):該區存放這個程式中所有的區域性變數,引數,臨時變數等。該區記憶體的管理由作業系統完成。

(3)堆區(heap):允許程式設計師自行動態的申請分配記憶體,記憶體的申請和釋放由程式設計師自己管理。該區的操作由尤其容易造成記憶體的提前釋放與記憶體洩露。

(4)全域性/靜態區。該區用來存放程式中的全域性變數以及靜態變數。程式在建立這一塊區域的時候會自動的將所有的位元組清零。所以全域性變數或者靜態變數的預設值時0.該區的釋放由作業系統完成。

(5)常量區:用來儲存程式中的文字常量以及字串常量。該區域的記憶體釋放也是由作業系統完成。

3.下面我們來看一下的一段**:

#include

using namespace std;

class one ;

class two ;

class two_1 ;

class two_2 ;

class two_3 ;

class three ;

class three_1 ;

int main()

//注釋部分為輸出的結果

cout << sizeof(one) << endl;//1

cout << sizeof(two) << endl;//4

cout << sizeof(two_1) << endl;//8

cout << sizeof(two_2) << endl;//4

cout << sizeof(two_3) << endl;//16

cout << sizeof(three) << endl;//16

cout << sizeof(three_1) << endl;//24

return 0;

}現在我們來分析這一結果:對於類這一復合資料型別,c++標準其實有解釋:

(1)不存在大小為0的資料型別,即使是類中不含任何資料,那麼它的大小是1,而不是零。

(2)物件的大小只與資料成員有關,與函式成員關。其實,在從上面的知識我們也可以推導出來,因為成員函式的儲存位置與資料成員的儲存位置不在乙個區域,sizeof不計算程式**區的記憶體。如此看來,實際上這個類的大小是比sizeof顯示的要大的。

(3)物件的大小計算是這樣規定的:1:各個資料成員與物件起始位址的偏移量必須是該資料型別的整數倍。2:類的大小必須是該類中最大資料型別的整數倍。這叫做記憶體對齊,記憶體對齊機制實際上是為了cpu更快的讀取記憶體。

知道了這些,我們來分析一下最後兩個類的大小區別的原因所在:觀察這兩個類可知,只是類中的資料成員的排序不同。首先,第一都是char,那麼距離類的起始位址的偏移量是0,那麼它首先占用乙個位元組。之後對於第乙個類來說就是int型,它的大小為四個位元組(我們在這了討論的基礎是基於32為作業系統),它對於類的起始位址偏移量是1,因為前邊有乙個char型別的資料佔據了乙個位元組。由於他要相對於類的起始位址的偏移量應該是自己本身大小的整數倍,所以他應該隔三個位元組之後在占用記憶體。也就是說,char型別與int型中間會出現三個空的位元組,以此來彌補int型別的位址到類的起始位址偏移量的不足。好了,那麼到現在前兩個一共佔據了八個位元組,對於第三個double來說,剛好滿足到類起始位址的偏移量等於自己大小的整數倍。所以doule直接就緊接著int開始佔據之後的八個位元組。那麼這個類的大小就是16個位元組。對於倒數第乙個類,分析也是一樣,首先是char佔據1個位元組,緊接著double相對於類的起始位址的偏移量是1,那麼需要補滿七個位元組,也就是說,char與double之間會有七個空位元組的間隔。緊接著int會佔據四個位元組,但是由於c++規定類的大小必須是該類最大資料成員大小的整數倍,那麼int之後還是會補足四個位元組,則這個類的大小就是24個位元組。

3.今天的分享就到這裡,其實c++中物件的記憶體布局比這些還要複雜一點。因為c++支援多型的機制,導致了在虛函式存在的情況下編譯器會給這個該物件新增乙個指標(我們叫虛指標),所以物件的大小會增加四個位元組。而且,對於靜態成員資料也是不影響物件的大小的。其實,sizeof函式計算的成員是在堆疊上的,對於其他記憶體區不予計算。

c 類的記憶體布局

本文基本上是對於stanley b.lippman的inside the c object model一書第一章第三章的概括,描述了c 類的記憶體布局情況.c 的類的記憶體布局有如下規則 1.nonstatic data member 存放在class object中 2.static data m...

c 類的記憶體布局

c 中的struct需要記憶體對齊,便於機器訪問該struct。每個物件 如果類含有虛函式 在首位址位置放置了vptr,指向自己的虛函式表。物件中不包含成員函式 靜態的或非靜態的 它們可以被物件共享,靜態成員函式沒有this指標,所以不能被物件呼叫,non static 成員函式隱含有乙個this指...

c 程式的記憶體布局

對任何乙個普通c 程式來講,它都會涉及到 5種不同的資料段。常用的幾個資料段種包含有 程式 段 程式資料段 程式堆疊段 等。不錯,這幾種資料段都在其中,但除了以上幾種資料段之外,程序還另外包含兩種資料段。下面我們來簡單歸納一下程序對應的記憶體空間中所包含的 5種不同的資料區。段 段是用來存放可執行檔...