C++類對象內存大小的計算?
class Point{
private:
short count;
int x,y;
public:
Point(int xx, int yy):x(xx),y(yy),count(0){};
~Point(){};
int getX(){return x;};
int getY(){return y;};
static string getInfo(){return "this is a String";}
};
上述的Point對象大小是sizeof(Point)=12, 很好理解, count(short)內存對齊佔4個bytes(單位已改正, 謝vczh提醒), x, y各佔4個bytes, 於是一共12個bytes。
class Point{
private:
short count;
int x,y;
public:
Point(int xx, int yy):x(xx),y(yy),count(0){};
virtual ~Point(){};
int getX(){return x;};
int getY(){return y;};
static string getInfo(){return "this is a String";}
};
當我把析構變為虛的之後, 大小變為了24個bytes, 我能理解這是內存按最大單位長度(指針的8bits)對齊後的結果。
但我不理解這24個bytes是怎麼分配的, 既然要對齊, 為什麼不是 4*8=32個bytes?ps, 順問問題二, 這樣的內存對齊的好處到底是什麼?
vtable(8) + count(2) + fuck(2) + x(4) + y(4) + fuck(4) = 24然而這單位是byte,不是bit。再說了,既然24可以,為啥要32?
你可以參考下我的這篇博客:
&<關於內存對齊的那些事&> http://darkc.at/about-data-structure-alignment/
對於struct(class也歸為此類)和union類型的變數,其成員是按照聲明的順序進行存儲的。
默認情況下,位元組對齊的規約是:對這些成員中的每一個成員而言:(1)若是基本數據類型(除此之外下文稱作「複合數據類型」)相對於整個struct和union類型變數的起始位置的偏移地址必須是該成員數據類型所佔位元組大小的整數倍,不足則填充最少的位元組;(2)若是struct或union複合數據類型,該成員相對於最外層struct和union類型變數的起始位置的偏移地址必須是該複合數據類型中所佔位元組空間最大的那個成員類型位元組的整數倍,而非整個複合類型所佔空間大小的整數倍,不足則填充最少的位元組。若該複合數據類型中仍含有複合數據類型成員則遞歸地進行判定;(3)struct和union類型的第一個成員的偏移地址等於該struct和union類型變數的起始地址;
(4)對於任何使用static關鍵字修飾的類型,其所佔的空間大小是不作為整個struct和union類型變數空間一部分進行考慮的,因此無所謂位元組對齊; (5) 整個struct和union類型變數所佔空間大小必須是其最大基本數據類型成員位元組大小的整數倍,若該成員為複合數據類型則按第2條遞歸下去直至最後的基本數據類型成員,不足則填充最少的位元組。在加入#pragma pack(n)後,位元組對齊的規約變成:對這些成員中的每一個成員而言:
(1)如果n大於等於該成員所佔用的位元組數,那麼其偏移量必須滿足默認的對齊方式,這只是針對此成員而言。只有當n大於等於所有這些基本數據類型大小時,所有成員才退化成默認位元組對齊,即這時#pragma pack(n)是不起作用的,仍採用默認對齊方式的規約;(2)如果n小於該成員所佔用的位元組大小,那麼該成員的偏移量只要滿足n的整數倍即可,而不用按照默認對齊方式。整個struct或union類型的空間大小必須是n的整數倍。
綜上:struct,class或union類型的位元組對齊值為編譯器默認或指示的位元組對齊值與每個成員類型空間大小中小的那一個!
內存對齊的好處是存取的效率高:比如要讀取32bit,在某平台上,其定址位置都是從偶地址開始,倘若該數據存放在以偶地址開始的地方,那麼一個讀周期就可以讀出,而如果存放在以奇地址開始的地方,就需要2個讀周期,並對兩次所讀出的數據按高低位元組位置進行合理的拼接才能得到該32bit數據。敢問題主用的什麼牌子的編譯器?
這是無virtual的
這是有virtual的其中內存對齊部分參考《深度探索c++對象模型》關於vptr我認為是這樣的count(2)+2(對齊)+x(4)+y(4)+vptr(4)=16因為是win32程序故內存對齊應該4的倍數,所以sizeof結果應該為16。至於24的版本,我認為題主使用的編譯器中的vptr為8byte,內存對齊也為8的倍數。24=vptr(8)+count(2)+2(對齊)+x(4)+y(4)+4(對齊)@vczh@魏凡丁題主 你需要這本書:
各成員變數存放的起始地址相對於結構的起始地址的偏移量必須為該變數的類型所佔用的位元組數的倍數。各成員變數在存放的時候根據在結構中出現的順序依次申請空間,同時按照上面的對齊方式調整位置,空缺的位元組自動填充。
同時為了確保結構的大小為結構的位元組邊界數(即該結構中佔用最大空間的類型所佔用的位元組數)的倍數,所以在為最後一個成員變數申請空間後,還會根據需要自動填充空缺的位元組。推薦閱讀:
※C++ 什麼時候不應該用虛函數?
※C++ 一個 class 裡面全部是靜態函數,這種設計目的是什麼?
※默認的逐成員初始化和逐位複製有什麼不同?