你們都知道,C++空類的內存大小爲1字節,爲了保證其對象擁有彼此獨立的內存地址。非空類的大小與類中非靜態成員變量和虛函數表的多少有關。html
而值得注意的是,類中非靜態成員變量的大小與編譯器內存對齊的設置有關。ios
成員變量在類中的內存存儲並不必定是連續的。它是按照編譯器的設置,按照內存塊來存儲的,這個內存塊大小的取值,就是內存對齊。函數
1、引入問題。大數據
#include<iostream> using namespace std; class test { private : char c='1';//1byte int i;//4byte short s=2;//2byte }; int main(){ cout << sizeof(test) << endl; return 0; }
輸出:12spa
class test2 { private: int i;//4byte char c = '1';//1byte short s = 2;//2byte }; int main(){ cout << sizeof(test2) << endl; return 0; }
輸出:8.net
咱們能夠看到。類test和test2的成員變量徹底同樣,只是定義順序不同,卻形成了2個類佔用內存大小不同。而這就是編譯器內存對齊的緣故。code
2、規則htm
一、第一個數據成員放在offset爲0的地方,之後每一個數據成員的對齊按照#pragma pack指定的數值和這個數據成員自身長度中,比較小的那個進行。對象
二、在數據成員完成各自對齊以後,類(結構或聯合)自己也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大數據成員長度中,比較小的那個進行。blog
很明顯#pragma pack(n)做爲一個預編譯指令用來設置多少個字節對齊的。值得注意的是,n的缺省數值是按照編譯器自身設置,通常爲8,合法的數值分別是一、二、四、八、16。
即編譯器只會按照一、二、四、八、16的方式分割內存。若n爲其餘值,是無效的。
3、問題分析
(1)對於類test的內存空間是這樣的:
內存分配過程:
一、char和編譯器默認的內存缺省分割大小比較,char比較小,分配一個字節給它。
二、int和編譯器默認的內存缺省分割大小比較,int比較小,佔4字節。只能空3個字節,從新分配4個字節。
三、short和編譯器默認的內存缺省分割大小比較,short比較小,佔2個字節,分配2個字節給它。
四、對齊結束類自己也要對齊,因此最後空餘的2個字節也被test佔用。
(2)對於類test2的內存空間是這樣的:
一、int和編譯器默認的內存缺省分割大小比較,int比較小,佔4字節。分配4個字節給int。
二、char和編譯器默認的內存缺省分割大小比較,char比較小,分配一個字節給它。
三、short和編譯器默認的內存缺省分割大小比較,short比較小,此時前面的char分配完畢還餘下3個字節,足夠short的2個字節存儲,因此short緊挨着。分配2個字節給short。
四、對齊結束類自己也要對齊,因此最後空餘的1個字節也被test佔用。
(3)使用#pragma pack(n)
#include<iostream> using namespace std; #pragma pack(1)//設定爲 1 字節對齊 class test { private : char c='1';//1byte int i;//4byte short s=2;//2byte }; class test2 { private: int i;//4byte char c = '1';//1byte short s = 2;//2byte }; int main(){ cout << sizeof(test) << endl; cout << sizeof(test2) << endl; return 0; }
輸出:
能夠看到,當咱們把編譯器的內存分割大小設置爲1後,類中全部的成員變量都緊密的連續分佈。
至此,C++內存對齊總結已經差很少了。想要更多瞭解C++對象內存分配推薦陳浩的2篇文章:
http://blog.csdn.net/haoel/article/details/3081328
和http://blog.csdn.net/haoel/article/details/1948051
陳浩大神寫的太透徹了。
參考:http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html
http://www.jb51.net/article/45406.htm