畫圈的地方是一個字節(jié)。上面截圖用的是16進制,一個16進制位搜贤,代表4個二進制位。兩個16進制位代表8個二進制位钝凶。一個字節(jié)由8個二進制位組成
如果一個結(jié)構(gòu)體里面就一個成員:比如
struct NSObject_IMPL {
Class isa; —> isa 占8個字節(jié)----指針在64的平臺中是占8個字節(jié)
}
因為這個struct NSObject_IMPL 結(jié)構(gòu)體只有一個成員
所以這個結(jié)構(gòu)體也只占8個字節(jié)
同一個結(jié)構(gòu)體里面的成員掂名,內(nèi)存地址是連續(xù)的
結(jié)構(gòu)體最前面的那個成員的地址值啃炸,就是結(jié)構(gòu)體的地址值铆隘。就好比數(shù)組首元素的地址卓舵,就是數(shù)組的地址
iOS 的CPU是小端模式南用,所以從內(nèi)存中讀取 04 00 00 00 讀取出來就是0x00000004
總結(jié),對象底層是一個結(jié)構(gòu)體掏湾,該結(jié)構(gòu)體首先包含父類的結(jié)構(gòu)體的現(xiàn)實裹虫,在包含自己的成員變量
一個oc對象系統(tǒng)最少會給它分配16個字節(jié)。
內(nèi)存對齊:就算沒有oc的至少16個字節(jié)的規(guī)定融击,內(nèi)存對齊有一條規(guī)則筑公,結(jié)構(gòu)體的大小必須是最大成員大小的倍數(shù)
@interface Person : NSObject
{
NSInteger a;//占4個自己
}
NSObject *obj = [[NSObject alloc] init];
NSLog(@"%zd",class_getInstanceSize([Person class]));
//獲取NSObject實例對象的成員變量所占用的內(nèi)存大小
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
NSLog(@"%zd",malloc_size((__bridge const void *)person));
//獲取obj指針所指向內(nèi)存大小
NSLog(@"%zd",malloc_size((__bridge const void *)objc));
2020-04-24 22:42:52.547269+0800 PrettyRuler[63943:1150801] 16
2020-04-24 22:42:52.547447+0800 PrettyRuler[63943:1150801] 8
2020-04-24 22:42:52.547539+0800 PrettyRuler[63943:1150801] 16
2020-04-24 22:42:52.547627+0800 PrettyRuler[63943:1150801] 16
malloc_size 返回的是系統(tǒng)實際分配給對象的內(nèi)存大小。
class_getInstanceSize返回的是內(nèi)存對齊后的結(jié)構(gòu)體的大凶鹄恕(返回的是一個類創(chuàng)建的實例對象所占用的內(nèi)存空間的大邢宦拧)
Person *person = [Person alloc] init];
我們創(chuàng)建出來的實例對象,alloc出來的這種實例對象只存有它的成員變量拇涤,方法是不會放到實例對象里面的捣作。成員變量每個實例對象都有一份,每個實例對象只要放自己特有的東西就好了鹅士。而方法都是一樣的券躁,所以只要一份就夠了,
面試題:一個NSOject對象占用多少內(nèi)存?
1.系統(tǒng)分配了16個字節(jié)給NSObject 對象(通過malloc_size函數(shù)獲得)
2.但NSObject對象內(nèi)部只使用了8個字節(jié)的空間(64bit環(huán)境下也拜,可以通過clss_getInstanceSize函數(shù)獲得)