OC 對象本質(zhì)

  • 我們平時編寫的OC代碼,底層都是C/C++代碼
    Object-C --> c/c++ --> 匯編語言 --> 機(jī)器語言
  • 所以O(shè)bject-C的面向?qū)ο蠖际腔赾/c++的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的。

下面就來思考一個問題:Object-C的對象、類主要是基于C/C++的什么數(shù)據(jù)結(jié)構(gòu)實現(xiàn)呢?
答案是:結(jié)構(gòu)體
至于為什么是結(jié)構(gòu)體,下面我們可以把NSObject對象代碼轉(zhuǎn)成c/c++代碼看下

將OC 代碼轉(zhuǎn)成c/c++代碼
  • xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 輸出的CPP文件
  • 如果需要鏈接其他框架,使用-framework參數(shù)。比如-framework UIKit
NSObject底層實現(xiàn)
@interface NSObject <NSObject> {  
    Class isa;
}
@end

//上面OC代碼轉(zhuǎn)成c++代碼后的實現(xiàn)
struct NSObject_IMPL {
    Class isa;
};

typedef struct objc_class *Class;

從上述代碼可以看到,其實一個NSObject對象,其實就是一個c++的結(jié)構(gòu)體,結(jié)構(gòu)體里面包含isa指針和成員變量。其中isa指針是一個指向結(jié)構(gòu)體的指針。

實例驗證:

@interface Student : NSObject

@property (nonatomic, assign) NSInteger height;
@property (nonatomic, copy) NSString *name;

@end


//c++代碼實現(xiàn)
struct Student_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    NSInteger _height;
    NSString * _Nonnull _name;
};

struct NSObject_IMPL {
    Class isa;
};
typedef struct objc_class *Class;


問題思考

一個NSObject對象會占用多少內(nèi)存?

  • 系統(tǒng)分配了16個字節(jié)給NSObject對象(通過malloc_size函數(shù)獲得)
  • 但NSObject對象內(nèi)部只使用了8個字節(jié)的空間(64bit環(huán)境下,可以通過class_getInstanceSize函數(shù)獲得)
@interface Student : NSObject
{
    @public
    int _no;
    int _age;
}
@end

@implementation Student

@end


 //這里通過指針直接賦值給studen的成員變量
 Student *stu = [[Student alloc] init];
 stu->_no = 4;
image.png

紅色框住的就是Student的內(nèi)存數(shù)據(jù)了,可以看到,在第九個字節(jié)就是04,就是我們所賦值給成員變量的值。那為什么只有一個成員變量Student的內(nèi)存數(shù)據(jù)占據(jù)了16個字節(jié)呢?
按道理來說前面isa指針占據(jù)8個字節(jié),一個int值得成員變量占據(jù)4個字節(jié),應(yīng)該是12個字節(jié)才對呀。

其實答案是:iOS 在64位系統(tǒng)下的內(nèi)存對齊是以16的倍數(shù)來對齊,比如說:像上面的實際是12個字節(jié),那么iOS底層為了內(nèi)存對齊,會給到16個字節(jié),那么如果剛好夠16個字節(jié)就不用再給了。

關(guān)于內(nèi)存對齊的文章大家可以自己去搜下,筆者在這里不做詳細(xì)展開。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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