这是我参与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结构体。 位域:
- 一种数据结构。
- 可以使数据单元节省存储空间。 联合体:
- 成员之间内存共用,各变量是“互斥”的。
- 可节省内存空间。
- 联合体的大小,为最大成员变量的大小。
- 一般会配合位域一起使用。
- 缺点:包容性较差