| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> isa与类关联的原理 -> 正文阅读 |
|
[C++知识库]isa与类关联的原理 |
alloc & init & new 源码分析文章中,alloc有3个核心操作,其中一个就是obj->initInstanceIsa,即类与isa绑定。主要理解类与isa是如何关联的。
探索对象本质
//以下两种方式是通过指定架构模式的命令行,使用xcode工具 xcrun
Clang clang是一个由Apple主导编写,基于LLVM的C/C++/OC的编译器 主要是用于底层编译,将一些文件``输出成c++文件,例如main.m 输出成main.cpp,
ZMPerson 的定义
疑问:为什么isa的类型是Class?
总结所以从上述探索过程中可以得出:
objc_setProperty 源码探索(name 对应的 set方法)
objc_setProperty的底层实现
objc_setProperty 的设计模式(适配器设计模式)objc_setProperty方法的目的适用于关联 上层的set方法 以及 底层的set方法,其本质就是一个接口 这么设计的原因
适配器设计模式(即将底层接口适配为客户端需要的接口)
下图是上层、隔离层、底层之间的关系 结构体与联合体构造数据类型的方式有以下两种:
结构体
优点:
缺点:
联合体
优点:
缺点:
结构体与联合体区别
isa 与 类 的关联原理isa的类型 isa_t
从isa_t的定义以下是isa指针的类型isa_t的定义,从定义中可以看出是通过联合体(union)定义的。
从isa_t的定义中可以看出: 提供了两个成员,cls 和 bits(互斥)
结构体定义的位域( ISA_BITFIELD)用于存储类信息及其他信息,结构体的成员ISA_BITFIELD,这是一个宏定义,有两个版本 arm64(对应ios 移动端) 和 x86_64(对应macOS),以下是它们的一些宏定义,如下图所示 nonpointer有两个值,表示自定义的类等,占1位
has_cxx_dtor 表示该对象是否有C++/OC的析构器(类似于dealloc),占1位
shiftclx表示存储类的指针的值(类的地址), 即类信息
magic 用于调试器判断当前对象是真的对象 还是 没有初始化的空间,占6位 weakly_refrenced是 指对象是否被指向 或者 曾经指向一个ARC的弱变量
deallocating 标志对象是是否正在释放内存 has_sidetable_rc表示 当对象引用计数大于10时,则需要借用该变量存储进位 extra_rc(额外的引用计数) — 导尿管表示该对象的引用计数值,实际上是引用计数值减1
针对两种不同平台,其isa的存储情况如图所示 isa_t类型使用联合体的原因也是基于内存优化的考虑,这里的内存优化是指在isa指针中通过char + 位域(即二进制中每一位均可表示不同的信息)的原理实现。isa指针占用的内存大小是8字节,即64位,已经足够存储很多的信息了,这样可以极大的节省内存,以提高性能 原理探索找到obj->initInstanceIsa源码
找到initIsa方法
该方法的逻辑主要分为两部分
isa 与 类 的关联cls 与 isa 关联原理就是isa指针中的shiftcls位域中存储了类信息,其中initInstanceIsa的过程是将 calloc 指针 和当前的 类cls 关联起来,有以下几种验证方式: 【方式一】通过initIsa方法中的newisa.shiftcls = (uintptr_t)cls >> 3;验证 【方式二】通过isa指针地址与ISA_MSAK 的值 & 来验证 【方式三】通过runtime的方法object_getClass验证 【方式四】通过位运算验证 方式一:通过 initIsa 方法
此时查看cls,是ZMPerson类 shiftcls赋值的逻辑是将 ZMPerson进行编码后,右移3位 执行lldb命令p (uintptr_t)cls,结果为(uintptr_t) $2 = 4294975720,再右移三位,有以下两种方式(任选其一),将得到536871965存储到newisa的shiftcls中 p (uintptr_t)cls >> 3 通过上一步的结果$2,执行lldb命令p $2 >> 3 继续执行程序到isa = newisa;部分,此时执行p newisa 与bits赋值结果的对比,bits的位域中有两处变化 cls 由默认值,变成了LGPerson,将isa与cls完美关联 所以isa中通过初始化后的成员的值变化过程,如下图所示 为什么在shiftcls赋值时需要类型强转?因为内存的存储不能存储字符串,机器码只能识别 0 、1这两种数字,所以需要将其转换为uintptr_t数据类型,这样shiftcls中存储的类信息才能被机器码理解, 其中uintptr_t是long isa.shiftcls 为什么需要右移3位?主要是由于shiftcls处于isa指针地址的中间部分,前面还有3个位域,为了不影响前面的3个位域的数据,需要右移将其抹零。 方式二:通过 isa & ISA_MSAK
方式三:通过 object_getClass通过查看object_getClass的源码实现,同样可以验证isa与类关联的原理,有以下几步: 1.main中导入#import <objc/runtime.h> 2.通过runtime的api,即object_getClass函数获取类信息
1.查看object_getClass函数 源码的实现 2.点击进入object_getClass 底层实现 3.点击ISA(),进入源码
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年4日历 | -2025/4/19 3:23:53- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |