iOS面試題-一個NSObject對象占用多少個字節(jié)?

一個NSObject對象占用多少個字節(jié)?

  • Objective-C中,我們可以通過一些方法來獲取一個NSObject對象占用多少字節(jié)

  • 代碼獲取NSObject實例對象的成員變量字節(jié)大小

    • 獲取一個NSObject實例對象的成員變量所占用的字節(jié)大小,可以用runtime的api, class_getInstanceSize來獲取,得到8
    /** 
     * Returns the size of instances of a class.
     * 
     * @param cls A class object.
     * 
     * @return The size in bytes of instances of the class \e cls, or \c 0 if \e cls is \c Nil.
     */
    OBJC_EXPORT size_t
    class_getInstanceSize(Class _Nullable cls) 
        OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
    
    • 也可以通過malloc庫里的api,malloc_size來獲取,得到16
    extern size_t malloc_size(const void *ptr);
    /* Returns size of given ptr */
    
  • 下面是實戰(zhàn)代碼

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>

// NSObject Implementation
struct NSObject_IMPL {
    Class isa; // 8個字節(jié)
};
// 指針
// typedef struct objc_class *Class;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
        // 16個字節(jié)
        
        // 獲得NSObject實例對象的成員變量所占用的大小 >> 8
        NSLog(@"%zd", class_getInstanceSize([NSObject class]));
        
        // 獲得obj指針所指向內(nèi)存的大小 >> 16
        NSLog(@"%zd", malloc_size((__bridge const void *)obj));
        
        // 什么平臺的代碼
        // 不同平臺支持的代碼肯定是不一樣
        // Windows粪狼、mac旨怠、iOS
        // 模擬器(i386)苫耸、32bit(armv7)咬摇、64bit(arm64)
        // 可以通過 命令行工具,生成C++文件
        // xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
        // 然后把編譯成功的cpp文件,拖入到工程中,注意 Copy items if needed 不勾選
        // 然后Build Phases中刪除main-arm64.cpp編譯選項(選中文件點減號或按delete鍵)
        // 這樣文件不參與編譯就不會報錯了
    }
    return 0;
}
  • 通過生成的編譯代碼,我們知道了NSObject對象本質(zhì)上是C++結(jié)構(gòu)體,結(jié)構(gòu)大概長這樣
// NSObject Implementation
struct NSObject_IMPL {
    Class isa; // 8個字節(jié)
};

通過objc源碼實現(xiàn)一探究竟

  • 現(xiàn)在蘋果的一些底層庫的核心實現(xiàn)源碼已經(jīng)開放,我們可以去官網(wǎng)下載

    • 地址https://opensource.apple.com/tarballs/objc4/
    • 選擇版本號最新的下載查看
  • 查看源碼發(fā)現(xiàn),一旦發(fā)現(xiàn)if size < 16 size = 16,小于16會直接設置為16

inline size_t instanceSize(size_t extraBytes) const {
        if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
            return cache.fastInstanceSize(extraBytes);
        }

        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }
  • CoreFoundation框架里的硬性規(guī)定,內(nèi)存對齊,小于16就會設置為16

用Xcode打斷點看內(nèi)存結(jié)構(gòu)

  • 打上斷點
image.png
  • Xcode菜單欄選中Debug -> Debug Workflow -> View Memory
image.png
  • 看到的內(nèi)存結(jié)構(gòu)如下圖所示
image.png
  • 也可以用常用的LLDB指令查看
image.png
  • 看到的打印如下圖所示
image.png

總結(jié)

  • 一個NSObject對象占用多少字節(jié)

回答

  1. 系統(tǒng)分配了16個字節(jié)給NSObject對象(通過malloc_size函數(shù)獲得)
  2. 但是NSObject對象內(nèi)部只使用了8個字節(jié)的空間(64bit環(huán)境下,可以通過class_getInstanceSize函數(shù)來獲取),其實就是isa

擴展到有繼承結(jié)構(gòu)的對象

  • Student繼承自NSObject
  • 代碼結(jié)構(gòu)如下
struct Student_IMPL {
    Class isa;
    int _no;
    int _age;
};


@interface Student : NSObject
{
    @public
    int _no;
    int _age;
}
@end

@implementation Student

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Student *stu = [[Student alloc] init];
        stu->_no = 4;
        stu->_age = 5;
        
        // 16
        NSLog(@"%zd", class_getInstanceSize([Student class]));
        // 16
        NSLog(@"%zd", malloc_size((__bridge const void *)stu));
        
        struct Student_IMPL *stuImpl = (__bridge struct Student_IMPL *)stu;
        // no is 4, age is 5
        NSLog(@"no is %d, age is %d", stuImpl->_no, stuImpl->_age);
    }
    return 0;
}
  • 大概的內(nèi)存結(jié)構(gòu)圖
image.png

擴展到有多重繼承的結(jié)構(gòu)

  • 如下圖繼承結(jié)構(gòu)
@interface Person: NSObject
{
    int _age;
}
@end

@implementation Person

@end

@interface Student : Person
{
    int _no;
}
@end

@implementation Student

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        // 16
        NSLog(@"person --- %zd", class_getInstanceSize([Student class]));
        // 16
        NSLog(@"person --- %zd", malloc_size((__bridge const void *)person));
        
        Student *stu = [[Student alloc] init];
        // 16
        NSLog(@"stu --- %zd", class_getInstanceSize([Student class]));
        // 16
        NSLog(@"stu --- %zd", malloc_size((__bridge const void *)stu));
    }
    return 0;
}
  • 結(jié)構(gòu)如下
image.png
  • 一個Person對象,一個Student對象占用多少內(nèi)存空間?
  • 答案是,都是16
  • 大概的內(nèi)存結(jié)構(gòu)圖
image.png
  • 有內(nèi)存對齊的原因,結(jié)構(gòu)體的大小必須是最大成員大小(16)的倍數(shù)

Objective-C不同數(shù)據(jù)類型占用字節(jié)大小

  • 可以通過sizeof來獲取不同數(shù)據(jù)類型占用字節(jié)大小
  • sizeof其實不是一個函數(shù),僅僅只是一個操作運算符罷了,編譯時就確定了的
類型 32位機器 64位機器
BOOL 1 1
bool 1 1
int 4 4
short 2 2
long 4 8
long long 8 8
NSInteger 4 8
float 4 4
double 8 8
CGFloat 4 8
char 1 1
指針地址 4 8
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市跌穗,隨后出現(xiàn)的幾起案子订晌,更是在濱河造成了極大的恐慌,老刑警劉巖蚌吸,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锈拨,死亡現(xiàn)場離奇詭異,居然都是意外死亡羹唠,警方通過查閱死者的電腦和手機奕枢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來佩微,“玉大人缝彬,你說我怎么就攤上這事〔该校” “怎么了谷浅?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我一疯,道長撼玄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任墩邀,我火速辦了婚禮掌猛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眉睹。我一直安慰自己荔茬,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布竹海。 她就那樣靜靜地躺著慕蔚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪站削。 梳的紋絲不亂的頭發(fā)上坊萝,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音许起,去河邊找鬼。 笑死菩鲜,一個胖子當著我的面吹牛园细,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播接校,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼猛频,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛛勉?” 一聲冷哼從身側(cè)響起鹿寻,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诽凌,沒想到半個月后毡熏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡侣诵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年痢法,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杜顺。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡财搁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躬络,到底是詐尸還是另有隱情尖奔,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站提茁,受9級特大地震影響淹禾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甘凭,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一稀拐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧丹弱,春花似錦德撬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至坯苹,卻和暖如春隆檀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粹湃。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工恐仑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人为鳄。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓裳仆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孤钦。 傳聞我的和親對象是個殘疾皇子歧斟,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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