咱們平時寫的 OC
代碼底層實現爲 C/C++
代碼,由於 Runtime
讓 OC
具有了面向對象的特色,然後底層的 C/C++
會轉換成底層的 彙編 代碼,最終被被解析成計算機能識別的 機器語言 。而 OC
中的類,正是正是基於 C/C++
的結構體實現的。咱們能夠經過 clang
命令將咱們平時所寫的 OC
代碼轉換爲 C/C++
代碼。這是轉換代碼:objective-c
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 源文件名 -o 目標文件名
複製代碼
若是須要連接其餘框架,使用 -framework參數
好比 -framework UIKit
bash
如: 咱們進入源文件所在的目錄,執行 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
會在當前目錄生成一個main.cpp的文件,這就是一個最簡單的OC文件的 C++
實現。app
經過轉換以後咱們很容易找到 NSObject
類的真正實現:框架
struct NSObject_IMPL {
Class isa;
};
複製代碼
只有一個 名爲 isa
的 Class
實例。繼續探尋 Class
的聲明:iphone
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
複製代碼
發現 Class
其實是一個指向 objc_class
的結構體指針。spa
也就是說 NSObject
最終聲明爲一個 指向結構體 objc_class
的名爲 isa
的結構體指針。既然是指針,在32位系統中佔 4個 字節,在64位系統中佔 8 個字節。如何查看本身的Mac是多少位呢?能夠在終端 輸入 uname -a
若末尾顯示 x86_64 則表明是64位系統,若是末尾顯示 i686 則表明是32 系統。目前咱們所使用的大多都是 64 位。指針
class_getInstanceSize
輸出一個類的實例對象的成員變量的大小NSObject *obj = [[NSObject alloc] init];
NSLog(@"%zd",class_getInstanceSize([obj class]));
複製代碼
輸出: code
因而可知,一個 NSObject 只有一個成員變量 即 isa,它所佔 8 個字節的大小。 咱們可經過 objc4源碼得出此結論。cdn
Class's ivar size rounded up to a pointer-size boundary. 一個類的全部成員變量所佔用的空間。對象
那在 OC
中一個 NSObject
對象佔用8個字節嗎?答案是否認的,咱們繼續分析。
malloc_size(const void *ptr)
輸出一個類實際分配的內存大小NSObject *obj = [[NSObject alloc] init];
NSLog(@"%zd",malloc_size((__bridge const void *)obj));
複製代碼
輸出:
2018-05-29 07:40:24.270554+0800 XWTest0[25108:1196172] 16
複製代碼
咱們知道在 OC
的對象實例中, 真正給對象分配內存的方式是
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
複製代碼
咱們能夠探究 allocWithZone
方法的底層實現, 一樣查看Apple開源的OC源碼 objc4源碼