Objective-C基础(三)

1. objc_class结构体

我们在OC中所写的每一个类,其底层其实都是利用struct结构体来实现的。其中objc_class就是用来保存类和元类对象的结构体。

学习这个结构体对于理解我们上篇文章中提到的OC对象以及之后要讲的Runtime等内容都有很大帮助。

结构体的定义如下(注:为了方便理解和记忆,只保留结构体中重要字段,其余字段省略):

struct objc_class {
    Class isa; // isa指针
    Class superclass; // superclass指针
    cache_t cache; // 方法缓存
    class_data_bits_t bits; // 指向具体的类信息的指针
}

其中,isa和superclass指针见上篇文章; cache是一个方法缓存,可以理解为一张哈希表,存储着这个类最近被调用的方法; bits是一个指针,指向一个class_rw_t结构体,其中包含具体的类信息。 class_rw_t结构体的定义如下:

struct class_rw_t {
    const class_ro_t *ro; // 指向只读信息
    
    struct method_list_t **methods; // 方法列表
    struct chained_property_list *properties; // 属性列表
    struct protocol_list_t ** protocols; // 协议列表
}

首先,class_rw_t中的rw意为readwrite,即这个结构体是可读写的,这也表明类的方法列表,属性列表,协议列表,是可读写的,这在之后的Runtime中会有相应的体现,大家可以先记住。 其次,class_ro_t中的ro意为readonly,即这个结构体指针指向的结构体是只读的(被const修饰),class_ro_t的定义如下:

struct class_ro_t {
    uint32_t instanceSize; // instance对象占用的内存
    const char * name; // 类名
    const ivar_list_t * ivars; // 成员变量列表
}

首先,上一篇文章中我们讲到,instance对象中,仅保存成员变量的值,因此,如果成员变量列表ivars是不变的,那么instance对象占用的内存instanceSize自然是不变的,因此他们是只读的。 其次,一个类的类名始终不变。

注意:objc_class用来保存类和元类对象,也就是说class对象和meta-class对象的内存结构是一样的。我们在上篇文章中提到过,class对象存储着属性信息、方法信息、协议信息和成员变量信息;而meta-class对象只存储类方法信息,因此meta-class的属性信息、协议信息、成员变量信息这些字段虽然存在,但是值为空。

关于源代码,请参考Apple官方:https://opensource.apple.com/source/objc4/objc4-437/runtime/objc-runtime-new.h.auto.html

2. getInstanceSize / malloc_size / sizeof

  1. getInstanceSize计算的是一个OC对象 至少需要的内存,存在结构体内存对齐,即结构体大小必须是最大成员大小的倍数。
  2. malloc_size计算的是一个OC对象 实际占用的内存,存在系统内存对齐,即对象占用内存大小必须是系统规定的单位的倍数(栈内存8字节、堆内存16字节)。

举个例子,假设一个类不存在任何成员变量,那么在创建这个类的一个instance对象,instance对象中就只存储着一个指向类对象的isa指针,在64位操作系统下,这个指针占8字节。 那么,如果对这个对象调用getInstanceSize方法,返回的结果就是8字节,即这个对象至少需要的内存。 如果对这个对象调用malloc_size方法,由于对象存储在堆上,因此需要做系统内存对齐(扩展为16的倍数),返回的结果为16字节,即这个对象实际占用的内存。 也就是说,在创建对象的时候,如果对象需要的空间小雨16字节,系统就会硬性分配16字节的空间给对象。

关于结构体内存对齐和系统内存对齐,面试官基本不咋考,感兴趣的同学可以上网搜索资料自行学习。

最后,关于sizeof,它与上面提到的两个函数之间的区别在于:

  • sizeof是运算符,不是函数
  • 只能计算基本数据类型的占用空间,不能传入一个OC对象
  • sizeof是运算符,其返回值在编译期就已经决定了,例如如果传入的是一个bool类型的变量,就返回1,int返回4。因此,它的运行效率比上面提到的两个函数要高

好啦,今天就先讲到这里。

我的牛客网账号是917470656,上面有我记录的几篇面经。

个人公众号:iOS开发学习

未经作者允许,禁止转载!

#iOS开发工程师##iOS开发工程师实习生##iOS工程师##iOS开发实习生##学习秋招#
iOS开发学习 文章被收录于专栏

学习iOS开发 == 手握大厂offer

全部评论

相关推荐

09-01 13:50
已编辑
字节跳动_客户端开发
不演了是吧,来吧,那就互爆,聊天记录.........................................................................................................................................................................................................................................!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!在此,请允许小弟我先诚恳的道个歉,这个标题是引流的。听说字节今年要招5000人,小弟也不知道最终这个数字具体是真是假,小弟目前能做的就是附上内推码并将各位兄弟姐妹们的流程跟进到底,小弟的🐎如下:【内推码:883G76D】(听说用这个内推码投递的都进字节了?)投递链接:https://job.toutiao.com/s/nSVy8-JLz6g最后,无论大家目前学历如何,当前面试过没过,最终会不会选择字节,小弟内心衷心祝愿大家最后都能收获满意的offer。如果大家有关于字节的公司文化、面试招聘、团队氛围、公司食堂、福利待遇等任何问题,大家可以在评论区互相讨论呦,小弟也定当知无不言!引流:
迷茫的大四🐶:输入内推码就能进入字节了吗
投递字节跳动等公司10个岗位
点赞 评论 收藏
分享
落花情:同学,瞅瞅我司,医疗独角兽,校招刚开,名额有限,先到先得,我的主页最新动态,绿灯直达,免笔试~
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务