OC對象的本質

OC的底層實現

OC代碼底層實現都是由OC編譯成C/C++,然后再編譯成匯編語言最后轉變成機器語言。所以由此可見,OC面向對象都是基于C/C++的數據結構實現的。

OC對象是基于C/C++的什么數據結構實現的?

NSObject *objc = [[NSObject alloc] init];

也就是說當我們創建一個新的NSObject對象的時候,在底層C語言或者C++這一層,objc這個對象是以一種什么數據類型存在的?
Xcode創建一個新項目,在macOS下->Command Line Tool
在Main.m中創建一個NSObject對象:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        
        NSObject *objc = [[NSObject alloc] init];
        
        
    }
    return 0;
}

生成了一個NSObject的實力對象objc,然后在利用Go2Shell打開重點,輸入:

xcrun  -sdk  iphoneos  clang  -arch  arm64  -rewrite-objc main.m -o main-arm64.cpp

回車之后我們會得到由OC語言轉化為C++語言的一個文件,main.cpp(main.c plus plus)


截屏2020-02-28下午8.32.59.png

打開這個文件,搜索NSObject,可以找到有個NSObject_IMPL,這個就是NSObject的實現

struct NSObject_IMPL {
    Class isa;
};

由此可知,main.m里這個objc對象在C++底層中是以struct的形式存在的,其實對于任何一個類的實例,因為所有類都是繼承NSObject其在底層實現都是以結構體形式存在的,實際上結構體這種數據類型來實現類是比較合適的方式。

繼承類的實現

如果有一個類Student繼承于NSObject類,那么他在底層中是如何實現的呢?
同樣按照NSObjct分析方式,創建Student類之后再講main.m轉換為main.cpp之后可以看到Student的實現方式:

struct Student_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _age;
    int _no;
};

在這里,還聲明了兩個實例變量,_no和_age,可以看到Student在底層中的實現也是結構體形式,但是其里面除了_no和_age兩個實例變量以外還有個struct NSObject——IMPL NSObject_IVARS類型,其實這個類型就是指的Student父類NSObject,他在子類實現中是以成員變量形式存在的。

一個NSObject對象占用多少內存?

基于以上分析,下面來討論一個NSObject對象占用多少內存,看這個問題之前先看下基本知識:

截屏2020-02-28下午8.51.57.png

現在基本都是64位機器,以64位機器為例,在OC中int占4個字節,NSInteger占8個字節。
除此之外OC中還有兩個函數:

class_getInstanceSize(<#Class  _Nullable __unsafe_unretained cls#>);
malloc_size(<#const void *ptr#>)

這兩個函數一個是在runtime下的一個是malloc下的,getInstanceSize函數是獲取實例的大小,malloc_size函數作用是創建一個實例對象實際分配多少內存,兩個函數還是有區別的:

        NSObject *objc = [[NSObject alloc] init];
        NSLog(@"創建NSObject實例所需要的內存空間為:%zd",class_getInstanceSize([NSObject class]));
        NSLog(@"創建NSObject實例所實際占用的內存空間為:%zd",malloc_size((__bridge const void *)objc));

輸出結果是不一樣的,一個是8個字節,一個是16個字節

2020-02-28 21:02:47.621864+0800 OC本質[74589:1018891] 創建NSObject實例所需要的內存空間為:8
2020-02-28 21:02:47.622331+0800 OC本質[74589:1018891] 創建NSObject實例實際占用的內存空間為:16

再來打印一下Student類通過兩個函數所占用空間:

@interface Student : NSObject
{
    int _age;
    int _no;
    double _height;
}

NSLog(@"創建NSObject實例所需要的內存空間為:%zd",class_getInstanceSize([Student class]));
NSLog(@"創建NSObject實例所實際占用的內存空間為:%zd",malloc_size((__bridge const void *)student));

2020-02-28 21:28:50.623604+0800 OC本質[75502:1041829] 創建NSObject實例所需要的內存空間為:24
2020-02-28 21:28:50.623998+0800 OC本質[75502:1041829] 創建NSObject實例所實際占用的內存空間為:32

通過打印結果可以看到,Student有三個成員變量,一個打印結果是24字節,一個是32字節,那么這兩個區別到底在哪里呢?
查看runtime源碼可以得出結論,class_getInstanceSize其實際是指的對象申請開辟的空間,即我有多少實例,占用多少字節那就申請多少字節空間,上面例子中,Student有三個實例變量
_age int類型 4個字節
_no int類型 4個字節
_height double類型 8個字節
所以加起來是16個字節,除此之外還有父類NSObject在底層也是在Student成員變量里面的又是8個字節,所以加起來實際需要24個字節,那么就申請24個字節。
那malloc_size中的32字節是怎么來的呢?
malloc_size指的是系統實際開辟的字節,明明只申請24字節,卻開辟32字節,是因為OC中有內存對齊規則的,簡單說就是申請的字節空間就是由我所有的成員變量加起來所需要的空間,但是系統真正開辟的空間是比申請空間大的數的對16的最小公倍數,比如實際需要24字節,但是24不是16的整數倍,那么大于24字節又是16整數倍的就是32了,所以系統開辟了32字節。

內存對齊規則

1.結構體內成員按自身按自身長度自對齊。
自身長度,如char=1,short=2,int=4,double=8,。所謂自對齊,指的是該成員的起始位置的內存地址必須是它自身長度的整數倍。如int只能以0,4,8這類的地址開始
2.結構體的總大小為結構體的有效對齊值的整數倍

OC中分配內存總結
對象內存的申請按照8字節對齊,不滿16字節按照16字節計算;但是實際上calloc實際開辟內存的時候,則是進行了16字節對齊.
關于內存對齊詳細解釋參考:
http://www.lxweimin.com/p/a57a152232f2

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容

  • iOS底層原理總結 - 探尋OC對象的本質 原文鏈接 對小碼哥底層班視頻學習的總結與記錄。面試題部分,通過對面試題...
    二斤寂寞閱讀 656評論 0 4
  • iOS底層原理總結 - 探尋OC對象的本質 對小碼哥底層班視頻學習的總結與記錄。面試題部分,通過對面試題的分析探索...
    xx_cc閱讀 21,498評論 31 178
  • 探尋OC對象的本質,我們平時編寫的Objective-C代碼,底層實現其實都是C\C++代碼,如圖所示: OC的對...
    二豬哥閱讀 566評論 0 6
  • 趕緊照照鏡子,臉上除了長出兩個痘皺紋倒是還是那些,這樣就安心啦。一如既往有點口渴,沒有饑腸轆轆,好像喝點水就可以,...
    萍心而論閱讀 1,826評論 1 4
  • 頭發的長度哪怕是只有5㎝,在我家人的眼里那就是超長。 我還記得剛上學前班那會兒,媽媽拿起剪刀把我還沒未及肩的頭發給...
    粥粥文閱讀 789評論 0 5