iOS 一個OC對象在內(nèi)存中的布局&&占用多少內(nèi)存

一.先來看看我們平時接觸的NSObject

  • NSObject *objc = [[NSObject alloc]init]的本質(zhì)
    在內(nèi)存中赋铝,這行代碼就把objc轉(zhuǎn)在底層實現(xiàn)中轉(zhuǎn)成了一個結(jié)構(gòu)體猬膨,其底層C++編譯成結(jié)構(gòu)體為:
struct NSObject_IMPL {
    Class isa;
};

在64位機(jī)中瓤漏,一個isa占8個字節(jié),在32位機(jī)中,一個isa占4個字節(jié)(當(dāng)然蘋果后面的機(jī)型都是64位的,這里我們著重講解64位機(jī))

  • 我們先來看看這個創(chuàng)建好的objc占多少個字節(jié)
int main(int argc, char * argv[]) {
    
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        //定義一個objc
        NSObject *objc = [[NSObject alloc]init];
        //打印內(nèi)存
        NSLog(@"tu-%zd",class_getInstanceSize([NSObject class]));
        NSLog(@"tu-%zd",malloc_size((__bridge const void *)(objc)));
    }
    
}

其打印結(jié)果為
objc打印結(jié)果
  • 為什么一個是8一個是16
    • 我們先來認(rèn)識一下class_getInstanceSize、malloc_size的區(qū)別
      1.class_getInstanceSize:是一個函數(shù)(調(diào)用時需要開辟額外的內(nèi)存空間)帽揪,程序運(yùn)行時才獲取,計算的是類的大懈ㄕ濉(至少需要的大凶)即實例對象的大小->結(jié)構(gòu)體內(nèi)存對齊
      2.創(chuàng)建的對象【至少】需要的內(nèi)存大小不考慮malloc函數(shù)的話,內(nèi)存對齊一般是以【8】對齊
      3.#import <objc/runtime.h>使用這個函數(shù)時倒入runtime運(yùn)行時

    • malloc_size:堆空間【實際】分配給對象的內(nèi)存大小 -系統(tǒng)內(nèi)存對齊

      1. 在Mac士飒、iOS中的malloc函數(shù)分配的內(nèi)存大小總是【16】的倍數(shù) 即指針指向的內(nèi)存大小
      2. import <malloc/malloc.h>使用時倒入這個框架
  • sizeof:是一個運(yùn)算符查邢,獲取的是類型的大小(int酵幕、size_t扰藕、結(jié)構(gòu)體、指針變量等)芳撒,這些數(shù)值在程序編譯時就轉(zhuǎn)成常數(shù)邓深,程序運(yùn)行時是直接獲取的

看到上面對兩個函數(shù)的認(rèn)識,應(yīng)該知道為什么輸出的一個是8笔刹,一個是16了吧芥备,當(dāng)內(nèi)存申請<16時,在底層分配的時候舌菜,系統(tǒng)會默認(rèn)最低16個字節(jié)萌壳,系統(tǒng)給objc16個字節(jié),而objc用到的是8個字節(jié)(沒添加任何成員變量之前)

二.內(nèi)存對齊

  • 在上面的基礎(chǔ)上我們新建一個類Student繼承NSObject日月,那么對于student的底層C++編譯實現(xiàn)就變成了:
struct Student {
    struct NSObject_IMPL NSOBJECT_IVARS;
};

也就是說袱瓮,繼承關(guān)系,子類直接將父類的isa引用進(jìn)來

  • 對于class_getInstanceSize(也就是類本質(zhì)的內(nèi)存對其)
    1.在student中創(chuàng)建成員變量:
@interface Student : NSObject
{
    @public
    int _age;
    int _no;
    int _tc;
}
@end

其底層C++編譯結(jié)構(gòu)體就變成了

struct Student {
    struct NSObject_IMPL NSOBJECT_IVARS;
    int _age;
    int _no;
    int _tc;
};

  • 打印結(jié)果:
 //定義一個objc
        Student *objc = [[Student alloc]init];
        //打印內(nèi)存
        NSLog(@"tu-%zd",class_getInstanceSize([Student class]));
        NSLog(@"tu-%zd",malloc_size((__bridge const void *)(objc)));

2020-09-08 12:35:27.158568+0800 OC底層[1549:79836] tu-24
2020-09-08 12:35:27.159046+0800 OC底層[1549:79836] tu-32

  • 先來說說24的由來

由于創(chuàng)建對象的時候爱咬,內(nèi)存是以8對齊懂讯,上面我們講到一個對象里面包含了一個isa占8個字節(jié),對于student來說它有四個成員變量台颠,isa,age,no串前,tc瘫里,共占8+4+4+4=20字節(jié),但是由于內(nèi)存以8對齊的原因荡碾,我們看到的輸出是24谨读,
結(jié)構(gòu)體8位對齊

所以class_getInstanceSize在計算實例大小的時候就是24,其白色區(qū)域表示空出了四個字節(jié)

  • 再來看看32的由來
    上面我們說到malloc_size指的是實際堆分配的空間坛吁,它以16字節(jié)對齊


    堆內(nèi)存對齊

可以看到劳殖,空白的區(qū)域為空出了12個字節(jié),總共為32個字節(jié)

三.添加屬性

  • 添加屬性
@interface Student : NSObject
{
    @public
    int _age;
    int _no;
    int _tc;

}
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSArray *array;
@end

其在底層C++編譯就變成了

struct Student {
    struct NSObject_IMPL NSOBJECT_IVARS;
    int _age;
    int _no;
    int _tc;
    NSString _name;
    NSArray _array;
};

默認(rèn)的會將屬性生成的_name添加進(jìn)結(jié)構(gòu)體中拨脉,計算相應(yīng)的大小

總結(jié):所以在實際計算類的占用空間大小的時候哆姻,根據(jù)添加的成員變量就可以計算出一個實例占用的內(nèi)存大小(即計算出結(jié)構(gòu)體的大小24玫膀,然后告訴系統(tǒng)矛缨,系統(tǒng)調(diào)用calloc分配內(nèi)存的時候按照16對齊原則分配)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市帖旨,隨后出現(xiàn)的幾起案子箕昭,更是在濱河造成了極大的恐慌,老刑警劉巖解阅,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件落竹,死亡現(xiàn)場離奇詭異,居然都是意外死亡货抄,警方通過查閱死者的電腦和手機(jī)述召,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碉熄,“玉大人桨武,你說我怎么就攤上這事⌒饨颍” “怎么了呀酸?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琼梆。 經(jīng)常有香客問我性誉,道長,這世上最難降的妖魔是什么茎杂? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任错览,我火速辦了婚禮,結(jié)果婚禮上煌往,老公的妹妹穿的比我還像新娘倾哺。我一直安慰自己轧邪,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布羞海。 她就那樣靜靜地躺著忌愚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪却邓。 梳的紋絲不亂的頭發(fā)上硕糊,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機(jī)與錄音腊徙,去河邊找鬼简十。 笑死,一個胖子當(dāng)著我的面吹牛撬腾,可吹牛的內(nèi)容都是我干的螟蝙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼时鸵,長吁一口氣:“原來是場噩夢啊……” “哼胶逢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饰潜,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤初坠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后彭雾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碟刺,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年薯酝,在試婚紗的時候發(fā)現(xiàn)自己被綠了半沽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吴菠,死狀恐怖者填,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情做葵,我是刑警寧澤占哟,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站酿矢,受9級特大地震影響榨乎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘫筐,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一蜜暑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧策肝,春花似錦肛捍、人聲如沸隐绵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氢橙。三九已至,卻和暖如春恬偷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帘睦。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工袍患, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人竣付。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓诡延,卻偏偏與公主長得像,于是被迫代替她去往敵國和親古胆。 傳聞我的和親對象是個殘疾皇子肆良,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354