废话不多说,要了解OC对象的本质,先要明确一点,都有哪些是属于OC的对象:实例对象,类对象,元类对象。
一,Object-C对象
1. instance (实例对象)
即alloc出来的对象,都会有单独自己的内存地址。
实例对象存储的信息主要有:
- isa指针
- 其他成员变量
2. class(类对象)
每个类在内存中有且只有一个class对象。
类对象存储的信息主要有:
- isa指针
- superclass指针
- 类属性信息、类的实例对象方法信息(值存储 -()xxx 这样的方法)
- 类协议信息、类成员变量信息(变量的类型和名称,不存储具体的赋值)
3. meta-class(元类对象)
每个类在内存中有且只有一个meta-class对象。
meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括
- isa指针
- superclass指针
- 类的类方法信息(class method +()xxx)
二,如何分析
大家都知道,OC最后要执行,都会转成机器语言(二进制),但是在这个过程中,还做了哪些转换呢?
其实,OC到机器语言,中间还经历了c/c++、汇编语言,最后才到机器语言的。具体看看下面这个图:

在这里我们主要分析的是:OC到c/c++这一层的转换,看看oc的类、对象所占内存、系统分配内存、及内存信息等
具体怎么操作呢?
1. 按照图示,将工程目录cd 到终端

第一个红框就是程序的main函数,程序的主入口
2. 在终端上输入
clang -rewrite-objc main.m -o main.cpp
表示重写main.m文件,最后输出为main.cpp文件

main.cpp中就是最终转换成C/C++的代码,只不过这种转换是全平台的转( win、iphone、Mac),我们并不需要所有的平台只需要iphone即可
3. 可以在终端敲入下面命令,可以生成只支持ios平台的c/c++代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
表示在xcode工具下运行 iphone平台,编译arm64架构,重写 mai.m文件,输出到 main-arm64.cpp文件
ios上的架构:模拟器(i386),32bit(armv7),64bit(arm64)

三,OC对象本质,具体分析
1. 先看看NSObject 转成 C/C++后,长啥样了
按照下图所示,找到相应代码,发现,这哥们最后变成了一个结构体
在这个文件里面搜所,大家会发现,好多基于NSObject的结构体,这就说明
【oc的对象、类主要是基于C/C++的结构体实现的】
struct NSObject_IMPL {
Class isa; // 这是一个指针,内存大小是8个字节
};

2. 看一道面试题
面试题:
一个 NSObject 对象占用多少内存?
可以理解为,它本身占了多少内存,系统给分配了多少内存
答案:系统分配了16个字节给NSObject对象(通过malloc_size函数获得),但是NSObject内部只使用了8字节空间(通过class_getInstanceSize函数获得)
我们已经知道了oc对象、类是基于c/c++的结构体数据类型实现的
所以,NSObject本身至少占8字节的内存,但是实际占多少呢,系统又给分配多少呢,看下面的例子
// 导入头文件
// #import <objc/runtime.h>
// #import <malloc/malloc.h>
NSObject *obj = [[NSObject alloc]init];
// 获取NSObject类的实例对象的成员变量所占用的大小,就是真正利用的 8 字节
// Class's ivar size rounded up to a pointer-size boundary.
NSLog(@"%zd", class_getInstanceSize([NSObject class]));
// 获取obj所指向内存的大小,就是系统分配的有 16 字节
// 搜索 allocWithZone 可以查看
// CF requires all objects be at least 16 bytes.
NSLog(@"%zd", malloc_size((__bridge const void *)(obj)));
从上面的例子中我们可以看出,可以通过两个函数来获取实际占用内存和系统分配内存的大小
可以在 https://opensource.apple.com/tarballs/objc4/ 查看 objc的源码, 就知道了 class_getInstanceSize 和 malloc_size 的本质
四,总结
OC对象、类是基于c/c++的设么数据结构实现的
主要是基于结构体实现的,这个可以通过查看源码验证
只要大家抓住这个本质,就会很容易分析出来一个实例对象到底站用多少内存,存储的信息都有哪些
思考:如果创建一个基于NSObject的类,里面有几个成员变量,再来分析一下内存结构,看看有什么不同的