iOS底層原理總結--OC對象的本質(二)

iOS底層原理總結--OC對象的本質(一) - 掘金xcode

iOS底層原理總結--OC對象的本質(二) - 掘金工具

iOS底層原理總結--OC對象的分類:instance、class、meta-calss對象的isa和superclass - 掘金post

iOS底層原理總結-- KVO/KVC的本質 - 掘金ui

...spa

思考: 若是個人Student有三個成員變量 那麼會佔用對少個字節? (class_getInstanceSize([Student class]) 的輸出是多少? malloc_size((__bridge const void *)stu的輸出是多少? )3d

#import <malloc/malloc.h>
#import <OBJC/runtime.h>
///> Student類
@interface Student: NSObject{
    @public
    int _no;
    int _age;
    int _gender;
}

///> 實際底層的結構體 結構
//struct Student_IMPL{
// Class isa,
// int _no,
// int _age;
// int _gender;

//}
@end

@implementation Student
@end

///> main
int main(int argc, char * argv[]) {
    @autoreleasepool {
        Student *stu = [[Student alloc]init];
        stu->_no = 4;
        stu->_age = 5;
        stu->_gender = 1; 
        NSLog(@"%zd", class_getInstanceSize([Student class]));
        NSLog(@"%zd", malloc_size((__bridge const void *)stu));        
        
        /**輸出結果 24 32 */ 
    }
    return 0;
}
複製代碼
  • 最終的輸出結果爲:
    • class_getInstanceSize: 24
    • malloc_size: 32

首先探究下一爲何malloc_size的輸出爲32 ?

可使用Xcode自帶的工具去查看 系統分配的內存和使用的內存狀況。指針

首先咱們須要拿到stu對象的內存地址: 調試

OC_%E6%89%93%E5%8D%B0%E5%86%85%E5%AD%98%E5%9C%B0%E5%9D%80log.png
xcode控制檯經常使用指令: Xcode調試器LLDB - 掘金

這裏咱們的內存地址爲:<Student: 0x600002746b60>code

OC_2_%E6%89%93%E5%BC%80viewMemory.png
而後選擇:Debug --> Degug Workflow --> View Memory

OC_2_ViewMemory_01.png
在下方的位置輸入咱們剛剛獲得的內存地址後就能夠了,stu的內存結構如上圖所示

OC_2_ViewMemory_02.png
直到紅線的位置都是stu所開闢的存儲空間,直到紅色數線後纔有了新的值, 在以前都是00值並且在內存中內存是連續的, 因此咱們能夠認爲,直到紅色豎線位置以前都是stu所分配的存儲空間

OC_2_ViewMemory_03.png
如上圖所示

  • 綠色區域:前8位就是咱們上節課所說的對象的本質實質上就是結構體:然而結構體中的帶有Class isa 指針,每一個對象中都會包含這個Class isa 這個指針。這個指針佔用了8個字節。
  • 藍色區域:成員變量_no:由於是Int類型因此真用了4個字節。
  • 黃色區域:成員變量_age:由於是Int類型因此真用了4個字節。
  • 灰色區域:成員變量_gender:由於是Int類型因此真用了4個字節。
  • 白色區域:全部的都是00,能夠認爲是已經開闢的的內存可是並無使用的區域。

由上圖分析:咱們能夠得出 stu實際上在內存中分配了32個字節的內存空間 也就是 malloc_size() 所輸出的開闢內存空間的字節數。cdn

接下來探究下一爲何class_getInstanceSize的輸出爲24 ?

class_getInstanceSize 顧名思義 獲取類的實例大小 isa佔用8個 + _no:4個 + _age4個 + _gender4個

@interface Student: NSObject{
    @public
    Class isa;   ///> 8
    int _no;     ///> 4
    int _age;    ///> 4
    int _gender; ///> 4
} /// 計算相加後 爲20個,
複製代碼

結構體存在一個內存對其的操做,這樣有利於CPU的訪問, 在CO中用到的內存對其的一條規則就是: 結構體爲了保證內存對其 最重的真用內存必定是佔用最大的一個變量的倍數, 在這裏咱們isa佔用了8個字節數, 因此雖然實際上只使用了20個字節,可是爲了保證內存對其的規則 因此使用了24個字節,

若是咱們有4個成員變量的話:

@interface Student: NSObject{
    @public
    Class isa;   ///> 8
    int _no;     ///> 4
    int _age;    ///> 4
    int _gender; ///> 4
    int _height; ///> 4
} /// 計算相加後 爲24個,
複製代碼

咱們真用的內存仍是24,開闢依舊是32個字節。

若是在增長一個成員變量的話:

@interface Student: NSObject{
    @public
    Class isa;   ///> 8
    int _no;     ///> 4
    int _age;    ///> 4
    int _gender; ///> 4
    int _height; ///> 4
    int _weight; ///> 4
} /// 計算相加後 爲28個,
複製代碼

爲了保證內存對其因此大小爲32個字節,開闢依舊是32個字節。

malloc_size() 也運用了內存對其的 上篇文章中解釋了爲何給類的內存分配了16個字節, 因爲內存對其的緣由因此stu類分配了32個字節。


  • 文章總結自MJ老師底層視頻。
相關文章
相關標籤/搜索