C++類對象成員變量和成員函數內存分配的問題

轉載:http://blog.csdn.net/xmu_jupiter/article/details/42648717

(轉載自:http://blog.sina.com.cn/s/blog_4feac7b90101keet.html)

很多人都知道C++類是由結構體發展得來的,所以他們的成員變量(C語言的結構體只有成員變量)的內存分配機制是一樣的。下面我們以類來說明問題,如果類的問題通了,結構體也也就沒問題啦。 類分爲成員變量和成員函數,我們先來討論成員變量。 一個類對象的地址就是類所包含的這一片內存空間的首地址,這個首地址也就對應具體某一個成員變量的地址。(在定義類對象的同時這些成員變量也就被定義了)我們來以一段代碼說明問題: //類的定義

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 這個單詞就主觀的認爲是存放在全局數據區,那是不對的

———-第二篇————

c++是一種面向對象的編程語言,它向下保持了對c的兼容,同時也允許程序員能夠自由的操控內存,雖然會帶來一些問題,但這不是我們要探討的問題,略過不表。類是對某種對象的定義,包含變量和方法,也可以理解爲現實生活中一類具有共同特徵的事務的抽象,他是面嚮對象語言的基礎。所以類是不佔有內存的,可是如果類生成實例那麼將會在內存中分配一塊內存來存儲這個類。

    類的實例在內存中是如何分配內存的,有什麼需要我們注意的,下面將慢慢到來。

    比如下面一個類:

    class A

    {};

    從形式上看,它似乎什麼有沒有,事實上它不止隱含了一個構造函數和一個析構函數,還有一些操作符重載函數,比如“=”。如果類A被實例話,如A a;在內存會佔據多大的空間呢?有人可能會說4,也有人會說0,還有人會說1,說1的就對了,爲什麼會是1呢?原因有很多,如果我們定義一個數組A b[10];如果上面是0,這樣的局面將會很尷尬,所以A這樣一個空類,編譯器會給它一個字節來填充。  

    增加一個變量,(字節對齊默認都是4)

    class  A

   {

     public:

       int i;

   }

  

   類A的實例將佔據4個字節的內存,sizeof(A) = 4

   變量i 的初值被編譯器指定位0xcdcdcdcd。

   再增加一個變量,

   class A

   {

      public:

      int  i;

      int  l;

   }

   此時按照變量生命的先後順序,i被放在低地址上,l緊隨其後。

   實例佔用8個字節,sizeof(A) = 4*2 = 8

   如果類裏面含有函數:

  class A

 {

     public:

      int i;

      int l;

      int add(int x,int y){return (x+y);}

 };

 有些人可能會說類的大小是12,事實上sizeof(A) = 8;

 爲什麼會這樣,這是因爲sizeof訪問的程序的數據段,而函數地址則被保存在代碼段內,所以最後的結果是8.

 再看下面這個情況

 class A

 {

      public:

         int i;

         int l;

         static int s;

         int add(int x,int y){return (x+y)};

 };

此時sizeof(A)大小仍爲8,這裏留給讀者去思考爲什麼?(^-^)。

當類裏面含有虛函數時,情況會如何呢?

 class A

 {

      public:

         int i;

         int l;

         static int s;

         virtual void Say(){};

         int add(int x,int y){return (x+y)};

 };

 因爲含有虛函數,所以類裏面將含有一個虛指針vptr,指向該類的虛表vtbl,一個指針佔用四字節的地址,所以sizeof(A) = 12

 虛指針放在類實例地址的最低位置,

 比如 A *a = new A;

 我們可以這樣給變量i賦值

 int *p = (int *)a;
 p++;
 *p = 1;//把i的值賦爲1.

如果類作爲派生類,內存將如何分配呢?

這種情況雖然有些複雜,但並不是說不好理解。

他有多少個父類每個父類的大小加起來在加上自身就是sizeof的大小。

轉自:http://blog.csdn.net/alexwei2009/archive/2011/01/22/6157926.aspx

 

//—–C++類對象內存結構[講得很好] ——-

首先介紹一下C++中有繼承關係的類對象內存的佈局: 
在C++中,如果類中有虛函數,那麼它就會有一個虛函數表的指針__vfptr,在類對象最開始的內存數據中。之後是類中的成員變量的內存數據。 
對於子類,最開始的內存數據記錄着父類對象的拷貝(包括父類虛函數表指針和成員變量)。 之後是子類自己的成員變量數據。 
對於子類的子類,也是同樣的原理。但是無論繼承了多少個子類,對象中始終只有一個虛函數表指針。 


發佈了7 篇原創文章 · 獲贊 50 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章