咱们平时写的 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源码