Clang如何将目标文件编译成c++文件
示例
对象是什么?
对象在底层的本质是结构体
NSObject的底层是objc_object,所以id的底层是objc_object *;
Class的底层是objc_class *
set和get方法的底层:
位域是什么?
-
我们先看一个结构体,根据结构体内存对齐可知该结构体所占内存为4个字节,但其实我们完全可以只用1位来存储1个布尔值。
-
所以我们便可以使用位域,图中的1代表1位,这样整个结构体只占1个字节,为什么是1个字节呢?因为没有半个字节,该结构体的内存大概示意为0000 1111,这样我们便可以大大节省内存空间。
联合体是什么?
联合体的结构如图所示,联合体中的成员变量是互斥的,比如当给name赋值时,age和height便没有数据或里面是脏数据,在特殊的场合下使用可以大大节省内存空间。
结构体和联合体的优缺点
结合联合体和位域使用
可以节省内存空间,但通常不建议使用,使用的时间成本大,建议只在特殊情况使用。
initIsa作用
将当前堆内存申请的结构体指针和class绑定在一起。
Isa底层结构
1. 初始化Isa
2. initIsa内部
3. 从上面可看出isa是通过isa_t初始化得来的,isa_t内部是联合体及结构体组合使用,如下图所示
4. 所以isa的实际内部结构在ISA_BITFIELD里面,如下图所示
5. 从上图可知,isa内部主要存储了以下内容:
- nonpointer: 表示是否对isa指针开启指针优化,0表示纯isa指针,1表示不只是类对象地址,isa中包含了类信息、对象的引用计数等。
- has_assoc: 关联对象标志位,0没有,1存在。
- has_cxx_dtor: 该对象是否有c++或者Objc的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象。
- shiftcls: 存储类指针的值;开启指针优化的情况下,在arm64架构中有33位用存储类指针。
- magic: 用于调试器判断当前对象是真的对象还是没有初始化的空间。
- weakly_referenced: 标志对象是否被指向或者曾经指向一个ARC的弱变量,没有弱引用的对象可以更快释放。
- deallocation: 标志对象是否正在释放内存。
- has_sidetable_rc: 当对象引用计数大于10时,则需要借用该变量存储进位。
- extra_rc: 当表示该对象的引用计数值,实际上是引用计数值减1,例如,如果对象的引用计数为10,那么extra_rc为9。如果引用计数大于10,则需要使用到下面的has_sidetable_rc。
通过isa反推出class
将isa地址和掩码做位运算
掩码
isa地址
做位运算
通过Isa联合体的信息做位运算
由上图可知,shiftcls存储的是类地址,所以只需要将isa地址左移3位,再右移20位,再左移17位,即可得到class地址,如下图所示
Init的意义
init方法内部实际并没有做什么事,作用在于提供接口,便于扩展 init 提供接口 便于扩展
New的意义
new方法其实就等于alloc + init