如何設(shè)計結(jié)構(gòu)體续徽?

今天這里聊聊如何設(shè)計結(jié)構(gòu)體,注意本文不介紹在C++中結(jié)構(gòu)體和類具體有什么區(qū)別纫版,本文所說的結(jié)構(gòu)體是指只有數(shù)據(jù)字段不帶任何函數(shù)的那種結(jié)構(gòu)體其弊。

當(dāng)創(chuàng)建結(jié)構(gòu)體的實例時膀斋,結(jié)構(gòu)體的數(shù)據(jù)成員會按其聲明的順序連續(xù)存儲。然而糊识,這個聲明的順序也是有學(xué)問的摔蓝,順序不同結(jié)構(gòu)體的大小可能有很大差別,數(shù)據(jù)成員的訪問性能也可能會有很大區(qū)別哑梳!

這里涉及一個概念:內(nèi)存對齊。關(guān)于內(nèi)存對齊這里不深入討論鸠真,只是簡單介紹一下。

大多數(shù)編譯器會對齊數(shù)據(jù)成員锡垄,會以四舍五入地址方式來優(yōu)化數(shù)據(jù)的訪問祭隔,如下表所示。

image

這種內(nèi)存對齊可能會在成員大小混合的結(jié)構(gòu)體中產(chǎn)生未使用字節(jié)的空洞千贯。

例如:

struct S {
    short int a; // 2字節(jié)
    // 6個空洞
    double b; // 8
    int d; // 4
    // 4個空洞
};
S ArrayOfStructures[100];

這里搔谴,在a和b之間有6個未使用的字節(jié)桩撮,因為b必須從一個能被8整除的地址開始。

最后還有4個未使用的字節(jié)空洞芜果。這樣做的原因是融师,數(shù)組中S的下一個實例必須從一個能被8整除的地址開始诬滩,以便將其b成員以8對齊。

然而疼鸟,如果改變一下結(jié)構(gòu)體中數(shù)據(jù)成員聲明的順序空镜,通過將最小的成員放在最后,未使用的字節(jié)數(shù)可以減少到2:

struct S {
    double b; // 8
    int d; // 4
    short int a; // 2
    // 2個空洞
};
S ArrayOfStructures[100];

這種重新排序使結(jié)構(gòu)體變小了8個字節(jié)张抄,那整個數(shù)組則變小了800個字節(jié)洼怔。

在此特性上,類和結(jié)構(gòu)體相同极谊。通過重新排序數(shù)據(jù)成員,結(jié)構(gòu)體對象和類對象通撤牵可以變得更小猜煮。如果類至少有一個虛成員函數(shù),則在第一個數(shù)據(jù)成員之前或最后一個成員之后會有一個指向虛函數(shù)表的指針王带。該指針在32位系統(tǒng)中為4字節(jié)辫秧,在64位系統(tǒng)中為8字節(jié)被丧。

如果不確定結(jié)構(gòu)體或它的每個成員有多大绪妹,可以使用sizeof操作符進行一些測試。sizeof操作符返回的值包括對象末尾的任何未使用的字節(jié)(內(nèi)存對齊后的字節(jié)數(shù))黄选。

也可以無腦使用緊湊型結(jié)構(gòu)體办陷?

還有一個知識點:

如果數(shù)據(jù)成員相對于結(jié)構(gòu)體或類開頭的偏移量小于128律歼,則訪問數(shù)據(jù)成員的代碼會更加緊湊险毁,因為該偏移量可以使用8位有符號的數(shù)字來表示。如果相對于結(jié)構(gòu)體或類的開頭的偏移量是128字節(jié)或更多畔况,那么偏移量必須表示為一個32位數(shù)字(指令集在8位到32位之間沒有偏移量)跷跪。例如:

struct S {
    int a[100]; // 400
    int b; // 4
    int read() { return b; }
};

b成員的偏移量是400。任何通過指針或成員函數(shù)訪問b字段的代碼都需要將偏移量編碼為32位數(shù)字嵌戈。如果交換a和b,則兩者都可以通過編碼為8位有符號數(shù)字的偏移量來訪問宽档,或者根本不需要偏移量庵朝。

這會使代碼更緊湊,方便更有效地使用代碼緩存九府。因此,建議在結(jié)構(gòu)或類聲明中肺蔚,大數(shù)組和其他大對象排在最后儡羔,最常用的數(shù)據(jù)成員排在前面。如果不能在前128個字節(jié)內(nèi)包含所有數(shù)據(jù)成員仇冯,則將最常用的成員放在前128個字節(jié)中苛坚。

通過上面兩個小知識點可以使得將結(jié)構(gòu)體設(shè)計的更小色难,訪問數(shù)據(jù)成員的速度更快枷莉,但是這有時往往會犧牲一些可讀性,比如這種結(jié)構(gòu)體:

struct S {
    int deskA;
    double deskB;
    bool deskC;
    int chairA;
    double chairB;
    bool chairC;
};

可能這樣修改后結(jié)構(gòu)體會更醒恼辍:

struct S {
    int deskA;
    int chairA;
    double deskB;
    double chairB;
    bool deskC;
    bool chairC;
};

但是我們一般情況下貌似希望同類的字段放在一起宋渔,這樣代碼可讀性更高一些辜限,易于讀懂代碼。至于這種結(jié)構(gòu)體具體需不需要重新排序颗胡,那就需要大家自己權(quán)衡啦吩坝。

小總結(jié):

  • 注意內(nèi)存對齊;
  • 128是個檻弧呐,常用的數(shù)據(jù)成員可考慮放在前128字節(jié)中俘枫,不常用的或大的數(shù)據(jù)成員可考慮放在后面(好久之前看的某個國外的博客學(xué)習(xí)到的鸠蚪,但是具體出處找不到了)师溅;
  • 注重性能優(yōu)化的同時也需要權(quán)衡一下代碼的可讀性险胰。

打完收工矿筝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窖维,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铸史,更是在濱河造成了極大的恐慌鼻疮,老刑警劉巖判沟,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挪哄,死亡現(xiàn)場離奇詭異迹炼,居然都是意外死亡斯入,警方通過查閱死者的電腦和手機刻两,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門磅摹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偏瓤,“玉大人厅克,你說我怎么就攤上這事证舟∷镀欤” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵女责,是天一觀的道長漆枚。 經(jīng)常有香客問我,道長抵知,這世上最難降的妖魔是什么墙基? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮刷喜,結(jié)果婚禮上残制,老公的妹妹穿的比我還像新娘。我一直安慰自己掖疮,他們只是感情好初茶,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浊闪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪折汞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天欠雌,我揣著相機與錄音禁炒,去河邊找鬼。 笑死们豌,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辩尊。 我是一名探鬼主播晾捏,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼胖齐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剿另?” 一聲冷哼從身側(cè)響起氛堕,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帮寻,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝉稳,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡饿这,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年串结,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出摇幻,到底是詐尸還是另有隱情引瀑,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布屡萤,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚊逢。 院中可真熱鬧,春花似錦桶至、人聲如沸圃郊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佩伤。三九已至须揣,卻和暖如春盐股,著一層夾襖步出監(jiān)牢的瞬間疯汁,已是汗流浹背溢豆。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工队他, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像掉分,于是被迫代替她去往敵國和親俭缓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容