iOS 底层探究:OC对象

310 阅读3分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

在OC面向对象编程中,我们每天都面对着创建对象,操作对象,那对象究竟是什么?实例化的对象和类的本质又是什么?

OC的类在C++的底层呈现

打开#import<objc/objc.h>文件

/// An opaque type that represents an Objective-C class.
//一个不透明类型用于表示Objective-C类
 typedef struct objc_class *Class;

 /// Represents an instance of a class. 
  //表示类的实例
 struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
 };

/// A pointer to an instance of a class.
typedef struct objc_object *id;

可以看出,OC中的类(Class)编译后在C++中是以 struct objc_class呈现的,我们众所周知的NSObject类编译后在C++中是一个struct objc_object,里面只有一个成员变量,即Class类型的变量isa。 在这里,我们也明白了为什么OC中的大部分对象了可以用id接收,因为id本身就是一个objc_object类型的结构体指针。 那么objc_object和objc_class是什么关系呢?其实我们自定义(继承于NSObject)的类,编译成C++对应的就是objc_class。 疑问:为什么isa的类型是Class?其根本原因是由于isa对外反馈的是类信息,为了让开发人员更加清晰明确,需要在isa返回时做了一个类型强制转换

结构体

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

缺点:所有属性都分配内存,比较浪费内存。假设有4个int成员,一共分配了16字节的内存,但是在使用时,你只使用了4个字节,剩余的12字节就是属于内存的浪费。

优点:存储容量较大,包容性强,且成员之间不会相互影响

联合体(共用体)

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

缺点:包容性弱。

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

位域

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1两种状态,用1位二进制位即可。为了节省存储空间,并使处理简单,C语言又提供了一种数据结构,称为“位域”或“位段”。 所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同对象用同一个字节的二进制位域来表示。

总结

对象本质:

  • 对象的本质是结构体。
  • 类也是对象,本质同样是结构体。
  • 万物皆对象,万物皆有isa。
  • isa本质是结构体指针,占8字节。
  • 所有对象的底层实现,本质上都来自于objc_object结构体。 位域:
  • 一种数据结构。
  • 可以使数据单元节省存储空间。 联合体:
  • 成员之间内存共用,各变量是“互斥”的。
  • 可节省内存空间。
  • 联合体的大小,为最大成员变量的大小。
  • 一般会配合位域一起使用。
  • 缺点:包容性较差