iOS底層原理總結--OC物件的分類:instance、class、meta-calss物件的isa和superclass - 掘金
iOS底層原理總結 -- 利用Runtime原始碼 分析Category的底層實現
...
思考: 如果我的Student有三個成員變數 那麼會佔用對少個位元組? (class_getInstanceSize([Student class]) 的輸出是多少? malloc_size((__bridge const void *)stu的輸出是多少? )
#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物件的記憶體地址:
xcode控制檯常用指令:Xcode偵錯程式LLDB - 掘金這裡我們的記憶體地址為:<Student: 0x600002746b60>
然後選擇:Debug --> Degug Workflow --> View Memory 在下方的位置輸入我們剛剛得到的記憶體地址後就可以了,stu的記憶體結構如上圖所示 直到紅線的位置都是stu所開闢的儲存空間,直到紅色數線後才有了新的值, 在之前都是00值而且在記憶體中記憶體是連續的, 所以我們可以認為,直到紅色豎線位置之前都是stu所分配的儲存空間 如上圖所示- 綠色區域:前8位就是我們上節課所說的物件的本質實質上就是結構體:然而結構體中的帶有Class isa 指標,每個物件中都會包含這個Class isa 這個指標。這個指標佔用了8個位元組。
- 藍色區域:成員變數_no:因為是Int型別所以真用了4個位元組。
- 黃色區域:成員變數_age:因為是Int型別所以真用了4個位元組。
- 灰色區域:成員變數_gender:因為是Int型別所以真用了4個位元組。
- 白色區域:所有的都是00,可以認為是已經開闢的的記憶體但是並沒有使用的區域。
由上圖分析:我們可以得出 stu實際上在記憶體中分配了32個位元組的記憶體空間 也就是 malloc_size() 所輸出的開闢記憶體空間的位元組數。
接下來探究下一為什麼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老師底層視訊。