iOS—对象的本质(学习笔记)

只是小小记录一下,内容不完整

  1. OC底层实现是c\c++,oc的面向对象都是基于c\c++实现
  2. NSObject c++ 底层结构
struct NSObject_IMPL {
	//CLass 指针,64位占8个字节
	__unsafe_unretained Class isa;
};

//Class
typedef struct objc_class *Class

oc中的定义

@interface NSObject <NSObject> {

    Class isa  OBJC_ISA_AVAILABILITY;

}
//
typedef struct objc_class *Class;
  1. 一个NSObject对象占用多少内存?
  • 系统分配了16个字节给nsobject对象(通过malloc_size函数获得)
    通过查看alloc源码,可以看到为NSObject对象分配内存时,硬性规定至少为16字节
    在这里插入图片描述

  • 但NSObject对象实际只使用8个字节(64位环境下,通过class_getInstanceSize获得,其实际调用的函数如下,从注释中可知这是成员变量的大小,返回的是内存对齐后的大小)
    返回内存对齐
    在这里插入图片描述


#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>

@interface Student : NSObject

@property (nonatomic, assign) char num;
@property (nonatomic, assign) int age;

@end

@implementation Student

@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
//        // insert code here...
  
        Student *stu = [[Student alloc] init];
		stu.age = 10;
        stu.num = 'a';
        
        //class_getInstanceSize返回的是类的对象的成员变量所占内存大小(对齐过的)
        NSLog(@"%lu", class_getInstanceSize([Student class]));
		
		//返回stu指针所指向的内存大小
        NSLog(@"%lu", malloc_size((__bridge const void *)stu));
        
    }
    return 0;
}

//打印结果
//2021-07-21 16:19:36.975209+0800 对象的本质[27424:2825069] 16
//2021-07-21 16:19:36.977476+0800 对象的本质[27424:2825069] 16



//转为c++, Student本质
struct Student_IMPL {
	struct NSObject_IMPL NSObject_IVARS;   //只有isa, 8个字节
	char _num;  //1
	int _age;   //4
};

//NSOject本质
struct NSObject_IMPL {
	__unsafe_unretained Class isa;
};

在这里插入图片描述
分别存储着num,age(16进制, iOS是小端模式,内存读取要反着读)
在这里插入图片描述

!!!内存对齐 结构体嵌套 学习!!!!!

  1. 结构体内存对齐原则:
  • 第一个成员从偏移量为0开始存储,其余成员从地址为自身大小的整数倍开始存储。
  • 成员为结构体时,该结构体从地址为其最大成员的整数倍开始存储
  • 结构体的总大小,即sizeof()出来的结果是其最大成员大小的整数倍。
  1. 补充
  • 获取内存大小

  • sizeof:操作符:
    传入数据类型,输出内存大小。编译时固定,只与类型相关,与具体数值无关。(如:bool 2字节,int 4字节,对象(指针)8字节)

  • class_getInstanceSize: runtime的api,传入对象,输出对象实际所占的内存大小,本质是对象中成员变量的大小。与sizeof()返回值相同。

  • malloc_size:
    获取系统实际分配的内存大小
    有一个对齐的概念,与内存对齐概念不同,为oc对象分配的内存大小为16字节倍数,空间换时间,以16字节为一块,这就保证了CPU在读取的时候,按照块读取就可以,效率更高,同时还不容易混乱。()

  1. oc对象的分类
  • instance对象,实例对象
    在内存中存储的信息 有isa、成员变量的具体值
  • class对象,类对象
    类对象在内存只有一份

在这里插入图片描述
在这里插入图片描述
类对象存储的内容为
isa指针、superclass指针
类的属性信息、类的对象方法信息
类的协议信息、类的成员变量信息

  • meta-class对象,元类对象
    object_getClass获取元类对象,参数为类对象
    注意:class方法返回的对象一定是类对象,不是元类对象
    每个类只有一个元类对象
    在这里插入图片描述
    在这里插入图片描述
    元类对象存储的内容:
    isa、superclass指针
    类方法
  1. objc_getClass(<const char * _Nonnull name>)
    参数为字符串类名,返回相应的类对象

object_getClass(id _Nullable obj)
参数为实例对象,返回类对象
参数为类对象,返回元类对象
参数为元类对象,返回NSObject(基类)

  1. isa指针
    实例对象isa指向类对象
    类对象isa指向元类对象
    元类对象isa指向基类的元类对象
    在这里插入图片描述

实际上,在64bit开始,isa需要进行一次位运算即 isa & ISA_MASK,才能计算出指向的类或元类对象的真实地址
对于ISA_MASK的定义
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • struct objc_class的结构
//objc-runtime-new.h中

//继承的objc_object下面有复制部分 里面的成员只有isa
//
struct objc_class : objc_object {
  objc_class(const objc_class&) = delete;
  objc_class(objc_class&&) = delete;
  void operator=(const objc_class&) = delete;
  void operator=(objc_class&&) = delete;
   
    // Class ISA;
    Class superclass;
    cache_t cache;             // 方法缓存 formerly cache pointer and vtable
    class_data_bits_t bits;    // 用于获取具体的类信息 class_rw_t * plus custom rr/alloc flags

	...
}

struct objc_object {
private:
    isa_t isa;

public:
	...
	//一些方法
}

struct objc_class的结构可以简化为

struct objc_class {
   // Class ISA;
    Class superclass;
    cache_t cache;             // 方法缓存 formerly cache pointer and vtable
    class_data_bits_t bits;    // 用于获取具体的类信息 class_rw_t * plus custom rr/alloc flags

}

在这里插入图片描述

  • 对class_rw_t的理解
    rw代表可读可写
    类中的属性、方法、协议等信息都保存在class_rw_t中

  • 对class_ro_t的理解
    ro代表只读
    存储了当前类在编译期就确定了的属性、方法、协议

OC对象中存储的属性、方法、遵循的协议数据其实被存储在这两块儿内存区域的,而我们通过runtime动态修改类的方法时,是修改在class_rw_t区域中存储的方法列表

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值