我們平時編寫的Objective-C代碼,底層實現(xiàn)其實都是C\C++代碼。
所以Objective-C的面向?qū)ο?/code>都是基于
C\C++的數(shù)據(jù)結構
實現(xiàn)的。
思考:那么是基于什么數(shù)據(jù)結構
實現(xiàn)的呢?
猜測:結構體。因為只有結構體才能容納不同類型葡缰。
探索:
- 探索思路:我們將OC文件轉化為C++文件來探尋OC對象的本質(zhì)
- 探索操作:利用clang重寫OC文件亏掀,轉換為c++文件
clang -rewrite-objc main.m -o main.cpp
// 竟然有9萬+行的代碼,因為不同硬件平臺的代碼不一樣泛释,我們只關注iOS上的代碼滤愕。
// 所以要指定arm64架構。
// 指定了架構怜校,就只生成arm64架構的代碼间影,才3萬+行代碼
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
打開main.cpp文件,搜索NSObjcet_IMPL
茄茁,查看NSObject的內(nèi)部實現(xiàn)魂贬,發(fā)現(xiàn)是一個結構體,如圖:
- 探索總結:
- OC類的底層實現(xiàn)就是一個結構體裙顽。那么NSObject對象在內(nèi)存中就是一個結構體付燥。
- 跟到Class里面查看發(fā)現(xiàn)
typedef struct objc_class *Class
,isa是一個指針愈犹。 - obj 和 isa指向的地址相同键科。
分析內(nèi)存結構
方式:通過打斷點。
Debug Workflow -> viewMemory address中輸入內(nèi)存的地址。
可以看到分配了連續(xù)16個字節(jié)給這個對象勋颖,其中前8個字節(jié)已經(jīng)被isa指針占用嗦嗡。
實例分析
創(chuàng)建一個類,繼承自NSObject饭玲,為這個類定義兩個int類型的屬性侥祭,這個對象占用多少內(nèi)存?
我們知道咱枉,系統(tǒng)為對象分配內(nèi)存都是連續(xù)的彤路,那從右邊的內(nèi)存地址可以分析出內(nèi)存大小。
提問封孙,一個NSObject對象占用多少內(nèi)存主慰?
#import <objc/runtime.h>
#import <malloc/malloc.h>
NSObject *obj = [[NSObject alloc] init];
//獲得NSObject類的實例對象的大小
NSLog(@"%d",class_getInstanceSize([NSObject class])); //最少需要8個字節(jié)內(nèi)存
//獲得obj指針所指向內(nèi)存的大小,malloc就是分配內(nèi)存的作用
NSLog(@"%zd",malloc_size((__bridge const void *)(obj))); //實際分配了16字節(jié)內(nèi)存
答案:NSObject在調(diào)用alloc時系統(tǒng)為其分配了16個字節(jié)亿乳,其中8個字節(jié)用來放isa結構體硝拧。
看蘋果的源碼里有個判斷,如果一個對象申請的內(nèi)存小于16個字節(jié)葛假,會為這個對象分配16個字節(jié)障陶,
蘋果這么做,可能是遵循了內(nèi)存對齊機制聊训。有利于提高cpu計算速度抱究。所以最終內(nèi)存大小應該是8的倍數(shù)。