C 記憶體詳解(二)

2021-07-02 20:49:25 字數 2496 閱讀 9259

在本文中主要是介紹c++中類在例項化過程中在記憶體中的分配。

很多人都知道c++類是由結構體發展而來,所以他們的成員變數(c語言的結構體只有成員變數,c++的結構體和類基本相同,除了預設成員變數的屬性,類成員變數預設私有,結構體成員變數預設公有,c++保留結構體主要是相容c程式)的記憶體分配機制是一樣的。下面我們以類來說明問題,如果類搞清楚了,結構體也就明白了。類分為成員變數和成員函式,我們先討論成員變數。乙個類物件的位址就是類所包含的這一片記憶體空間的首位址,

類定義:

class k

~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指標,因此不能訪問非靜態資料成員,就像我們前面提到的,所有函式都存放在**區,靜態函式也不例外。

c++是一種物件導向的程式語言,它向下儲存了對c的相容,同時也允許程式設計師能夠自由的操控記憶體,雖然會帶來一些問題,但是這不是本文討論的問題。類是對某種物件的定義,包括變數和方法,也可以理解為現實生活中一類具有共同特徵的事物的抽象,它是物件導向語言的基礎。所以類是不占有記憶體的。但是如果類生成例項,那麼將會在記憶體中分配一塊記憶體來儲存類物件。

類的例項化物件在記憶體中是如何分配記憶體的,請看下面的類:

class a {};

從形式上看,它似乎什麼也沒有,事實上它不知隱含了乙個建構函式和乙個析構函式,hi阿尤一些操作過載運算函式,比如」=「。如果a被例項化,例如:a a;在記憶體會佔據多大的空間?有人可能說是4,也有說是0,但是正確的答案是:1,為什麼是1?原因很多,比如說如我定義乙個陣列a[10];如果按上面說的是0,這樣的局面會很尷尬,所以a這樣乙個空類,編譯器給它乙個位元組來填充。

如果我們增加乙個變數,(位元組對齊預設為4):

class  a

類a的例項將佔據4個位元組的記憶體,sizeof(a)=4,變數i的初值被編譯器指定為0xcdcdcdcd。

如果再增加乙個變數:

class a

此時,按章變數生命的先後順序,i被放在了低位址上,l緊跟其後。例項物件占用8個位元組,sizeof(a)=4+4=8。

如果類裡面包含函式:

class a

};

這時,有人會可能會說類的大小為12,事實上sizeof(a)=8;

為什麼會這樣?這是因為sizeof訪問程式的資料段,而函式位址責備儲存在**段內,所以最後結果是8。

再看下面這個情況:

class a

; };

此時sizeof(a)大小仍是8,這是因為static變數在全域性區(靜態區),而非資料段

當然,類裡面含有虛函式時,情況就另當別論了!例如:

class a

; int add(int x,int y);

};

因為含有虛函式,所以類裡面將含有乙個虛指標vptr,指向該類的虛表vtbl,乙個指標占用四位元組的位址,所以sizeof(a)=12,虛指標放在類例項位址的最低位置,比如:a *a=new a;我們可以這樣給變數i賦值:

int *p = (int *)a;

p++;

*p = 1;//把i的值賦為1.

如果類作為派生類,記憶體將如何分配呢?

這種情況雖然有些複雜,但並不是說不好理解,它有多少個父類每個父類的大小加起來再加上自身就是sizeof的大小。

總結c++類物件記憶體結構:

首先介紹一下c++中有繼承關係的類物件記憶體的布局:

在c++中,如果類中有虛函式,那麼它就有乙個虛函式表的指標——vfptr,在類物件最開始的記憶體資料中,之後是類中的成員變數的記憶體資料。

對於子類,最開始的記憶體資料記錄著父類物件的拷貝(包括父類虛函式表指標和成員變數),之後是子類自己的成員變數資料。

對於子類的子類,同樣的原理,但是無論繼承多少個子類,物件中始終只有乙個虛函式表指標。

C 記憶體管理詳解

偉大的bill gates 曾經失言 640k ought to be enough for everybody bill gates 1981 程式設計師們經常編寫記憶體管理程式,往往提心吊膽。如果不想觸雷,唯一的解決辦法就是發現所有潛伏的地雷並且排除它們,躲是躲不了的。本文的內容比一般教科書的要...

C 記憶體對齊詳解

最近看各公司筆試和面試的試題,不少是關於c 記憶體對齊方面的。這個問題我以前也模模糊糊的了解一些,但總是不甚清楚。這次費了很大勁,終於算是搞明白了。整理出來,和大家分享一下。這一切要從機器字長和儲存字長說起。機器字長是cpu每次處理的二進位制的位數 儲存字長是記憶體中乙個儲存單元的包含二進位制位數,...

C 記憶體管理詳解

踏入c 中的雷區 c 記憶體管理詳解 這篇文章回答了我之前的乙個問題,就是分配記憶體用malloc好,還是用new好,今天跑程式的時候,發現malloc老是失敗,氣得不行,最後看到了這篇文章,原來如此,以後堅決用new了。1 有了malloc free為什麼還要new delete?malloc與f...