Objective-C对象的本质

  我们知道平时编写的OC代码,底层都是CC++代码:Objective-C -> C/C++ -> 汇编语言 -> 机器语言。所以Objective-C对象的底层实现就是CC++
  那么请思考问题:Objective-C对象,是基于C/C++什么类型的数据结构实现的?
  答案大家都知道,结构体。因为结构体可以存放不同的数据类型。想要看清OC的底层实现,我们可以使用下面①的命令行。但是编译后我们会发现,一个简单的文件就会编译出超过10万行的代码,这是因为clang在编译时候,是有不同的平台区分的,比如Windows平台,Mac平台。所以我们可以使用②的命令指定平台,这样代码就会简化很多。

1、clang -rewrite-objc main.m -o main.cpp
2、xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

  我们可以看找到一个类对象的实现,NSObject_IMPLNSObject implementation

struct NSObject_IMPL {
    Class isa;
};

  然后我们在定义一个类Student然后继续执行上面的命令,看看在底层转化是否是结构体如下所示。这里是Student_IMPL结构体的第一个成员变量就是NSObject。这样的好处就是我定义的Student类里拥有NSObject的所有属性。

struct Student_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

下面有个问题,为什么NSObjectisaClass类型的,通过之前的iOS开发之alloc和init分析,我们查看方法initInstanceIsa,我们可以看到isa的类型是isa_t(如下图isa_t),在底层进行了强转,类似于swift中的as,可以查看源码(如下图强转)。

isa_t
强转

总结:

1.OC的本质是结构体
2.子类的isa继承自父类

isa_t的类型

isa_t

  在这里我们看到了一个关键词union(共用体/联合体),构造数据类型的方式,有两种:

1、结构体(struct)。
2、联合体(union,或者叫共用体)。

结构体
结构体是指把不同的数据组合成一个整体,其变量是共存的,变量不管是否使用,都会分配内存。

  • 缺点:所有属性都分配内存,比较浪费内存,假设有4个int成员,一共分配了16字节的内存,但是在使用时,其实使用四个字节就可以表示。那么剩下的12个字节就属于浪费。
  • 优点:存储容量较大,包容性强,且成员之间不会相互影响

联合体
联合体也是由不同的数据类型组成,但其变量是互斥的,所有的成员共占一段内存。而且共用体采用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会将原来成员的值覆盖掉

  • 缺点:包容性弱
  • 优点:所有成员共用一段内存,使内存的使用更为精细灵活,同时也节省了内存空间

两者的区别
内存占用情况

  • 结构体的各个成员会占用不同的内存,互相之间没有影响
  • 共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员

内存分配大小

  • 结构体内存 >= 所有成员占用的内存总和(成员之间可能会有缝隙)
  • 共用体占用的内存等于最大的成员占用的内存
      我们继续回到isa_t的分析中,我们看内部实现,发现有两个变量,clsbits,上面我们讲述了共用体的特点,所以我们知道,isa的初始化方式有两种:一、通过cls初始化,那么bits没有默认值。二、通过bits初始化,cls没有默认值。而且详细的列除了isa的位域信息ISA_BITFIELD(如下图)。接下来,我们详细分析这些信息所代表的含义。
    位域

1.nonpointer

  • 0:纯isa指针
  • 1:不只是类对象地址,包含了类信息,引用计数等。

2.has_assoc表示是否有关联对象。
3.has_cxx_dtor表示该对象是否有C++/OC的析构函数。

  • 如果有析构函数,则需要做析构逻辑。
  • 如果没有,则可以更快地释放对象。

4.shiftclx表示存储类信息。arm64架构下33位,x86_64架构下占44位。
5.magic用于调试器判断当前对象是真的对象还是没有初始化的空间,占6位。
6.weakly_refrenced,是否被弱引用,没有可以更快释放。
7.deallocating表示对象是否正在释放内存。
8.has_sidetable_rc表示当对象引用计数大于10时,则需要借用该变量存储进位。
9.extra_rc(额外的引用计数) --- 导尿管表示该对象的引用计数值,实际上是引用计数值减1。如果对象的引用计数是10,那么extra_rc为9.

验证isa指针位域信息(0-64)
image.png

  上方的nonpointertrue,所以走下面的方法,进入第一个断点,我们进行lldb调试,返现newisa信息都为空,继续往下走,当走到newisa.bits = ISA_MAGIC_VALUE; define ISA_MAGIC_VALUE 0x001d800000000001ULL后,我们在进行调试(如下图)


  和上面的信息比较,我们得到了cls = 0x001d800000000001,在计算器中打开(如下图)
  我们发现从47位开始是111011,然后我们把计算器转换成10进制,输入magic = 59(如下图),同样的也是111011,在47号位置的值就是59。有没有感觉到很神奇,666!!!

  所以calloc的意义和我们之前文章里讲述的就一模一样了,是把isa和我们的类,关联起来。newisa.shiftcls = (uintptr_t)cls >> 3;,我们来进一步验证这行代码。经过赋值之后,我们看到newisashiftcls被赋值成功了,注意,我们上面是没有shiftcls的。右移三位是为了不覆盖原来的前三个位置的信息(nonpointer,has_assoc,has_cxx_dtor

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351