前言
上一篇文章我们研究的对象的内存
总结一下内存
LGPerson *person = [LGPerson alloc];
1.sizeof(person)
: 该运算符只是返回类型的大小
,而非实际的内存
因为isa结构体指针
占用8字节
2.
class_getInstanceSize([LGPerson class])
:传入一个类对象
,返回一个对象的实例至少需要多少内存,需要导入#import <objc/runtime.h>
,内存8字节对齐
3.
malloc_size((__bridge const void *)(person))
: 返回系统实际分配的内存大小,需要导入#import <malloc/malloc.h>
,内存16字节对齐
下面我们研究一下对象的本质 对象的本质的是什么呢
一.对象的本质
1.clang
是什么?
Clang
是⼀个C
语⾔、C++
、Objective-C
语⾔的轻量级编译器。源代码发布于BSD协议下。
Clang
将⽀持其普通lambda
表达式、返回类型的简化处理以及更好的处理constexpr
关键字。
Clang
是⼀个由Apple主导编写,基于LLVM
的C/C++/Objective-C
编译器
2013年4⽉,Clang
已经全⾯⽀持C++11
标准,并开始实现C++1y
特性(也就是C++14
,这是
C++
的下⼀个⼩更新版本)。Clang
将⽀持其普通lambda
表达式、返回类型的简化处理以及更好的处理constexpr
关键字。
Clang
是⼀个C++
编写、基于LLVM
、发布于LLVM BSD
许可证下的C/C++/Objective-C/
Objective-C++
编译器。它与GNU C
语⾔规范⼏乎完全兼容(当然,也有部分不兼容的内容,包括编译命令选项也会有点差异),并在此基础上增加了额外的语法特性,⽐如C
函数重载
(通过__attribute__((overloadable))
来修饰函数),其⽬标(之⼀)就是超越GCC
。
2.clang使用
clang -rewrite-objc main.m -o main.cpp
把⽬标⽂件编译成C++
⽂件
UIKit
报错问题
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot / Applications/Xcode.app/Contents/Developer/Platforms/ iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m
xcode
安装的时候顺带安装了xcrun
命令,xcrun
命令在clang
的基础上进⾏了
⼀些封装,要更好⽤⼀些
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp (模拟器)
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o mainarm64.cpp (⼿机)
3.clang搞一下
进入项目main
文件夹 添加XWTest
对象如下图
通过终端进入项目 执行 clang -rewrite-objc main.m -o main.cpp 生成 main.cpp
文件
查看main.cpp
文件源码 对象在底层的本质就是结构体 全局搜索XWTest
找到这里 如下图所示
全局搜索NSObject_IMPL
是我们熟知的isa
对象的本质是objc_object
类型
id person
我们平时为什么这么写
通过获取对象的首地址进行偏移进行get
取值 set
赋值的操作
二.位域
1.位域优化内存 例如:front:1 代表front占用1位
2.联合体互斥 结构体共存
结构体(struct)中所有变量是“共存”的——优点是“有容乃⼤”,
全⾯;缺点是struct内存空间的分配是粗放的,不管⽤不⽤,全分配。
联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”; 逻辑教育
但优点是内存使⽤更为精细灵活,也节省了内存空间
三.nonPointerIsa的分析
我们平时用的类也是指针 8字节*8 = 64位 大大的浪费了空间 苹果优化了一下 是否正在释放 引用计数 weak
关联对象 析构函数
要看位域 回到我们alloc
最后一步对象和指针地址进行绑定
进入到initIsa
进入到initIsa
进入到isa_t
点击进入
nonpointer
:表示是否对 isa 指针开启指针优化
0:纯isa指针,1:不⽌是类对象地址,isa 中包含了类信息、对象的引⽤计数等
has_assoc
:关联对象标志位,0没有,1存在
has_cxx_dtor
:该对象是否有 C++ 或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑,
如果没有,则可以更快的释放对象
shiftcls
: 存储类指针的值。开启指针优化的情况下,在 arm64 架构中有 33 位⽤来存储类指针
magic
:⽤于调试器判断当前对象是真的对象还是没有初始化的空间
weakly_referenced
:志对象是否被指向或者曾经指向⼀个 ARC 的弱变量,
没有弱引⽤的对象可以更快释放。
deallocating
:标志对象是否正在释放内存
has_sidetable_rc
:当对象引⽤技术⼤于 10 时,则需要借⽤该变量存储进位
extra_rc
:当表示该对象的引⽤计数值,实际上是引⽤计数值减 1,
例如,如果对象的引⽤计数为 10,那么extra_rc
为 9。如果引⽤计数⼤于 10,
则需要使⽤到下⾯的has_sidetable_rc
。
四.isa推到class
对象的首地址&掩码地址得到类的地址、
掩码地址:define ISA_MASK 0x00007ffffffffff8ULL