文章目录
- 一、Objective-C的本质
- 二、一个objc对象如何进行内存布局?考虑父类的情况
- 三、一个objc对象的isa指针指向什么?有什么作用
- 四、objc对象的类方法和实例方法有什么本质区别和联系?
一、Objective-C的本质
- Objc的底层实现是C\C++代码:objc->C\C+±>汇编->机器语言
- Objc的对象,类主要是基于C\C++中的结构体实现
- 将Objc代码转换为C\C++代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
二、一个objc对象如何进行内存布局?考虑父类的情况
类结构图:
对象的底层实现
- oc的代码
@interface Person : NSObject
{@publicint _age;
}
@end@interface Student : Person
{@publicint _no;
}
@end@interface Graduate : Student
{@publicint grade;
}
@end@implementation Graduate@end
对应的C++代码
struct NSObject_IMPL {Class isa;
};struct Person_IMPL {struct NSObject_IMPL NSObject_IVARS; // 8int _age; // 4
};struct Student_IMPL {struct Person_IMPL Person_IVARS; int _no;
}; Student *stu = [[Student alloc] init];stu->_age = 2;stu->_no = 3;NSLog(@"stu - %zd", class_getInstanceSize([Student class])); // 16NSLog(@"stu - %zd", malloc_size((__bridge const void *)stu)); // 16Graduate *grade = [[Graduate alloc] init];
grade->_age = 7;
grade->_no = 8;
grade->grade = 9;
NSLog(@"grade - %zd", class_getInstanceSize([Graduate class])); // 24
NSLog(@"grade - %zd", malloc_size((__bridge const void *)grade)); // 32
- 64位系统下, 可以看出,编译给Person分配了16个字节,实际用到12个字节,还有4个字节没有使用, Student对象继承Person对象,Student对象实际会继续使用Person对象内存中没有使用的4个字节,所以Student对象的内存大小是16个字节,Grade继承Student类,实际占用的内存大小为20个字节,由于内存对齐原因,以8个字节内存对齐,所以会使用24个字节,编译器分配了32个字节
- 内存对齐:结构体的大小必须是最大成员大小的倍数
总结:
- 就是多了一个isa指针,isa的大小由编译器,系统决定,内存分配编译器按照内存对齐进行大小分配,分配的内存,不一定会完全用完
class_getInstanceSize获取实例对象至少占用的内存
malloc_size获取编译器给实例对象对象分配的内存的大小
在 libmalloc源码中定义了 #define NANO_MAX_SIZE 256 /* Buckets sized {16, 32, 48, 64, 80, 96, 112, …}表示在iOS系统中每次最少分配16个字节,或者每次分配的字节数是16的倍数,每次最多分配256字节
三、一个objc对象的isa指针指向什么?有什么作用
- 实例变量的isa指针指向他所属的类
- 类的isa指针指向他所属的原类
- 原类的根类的isa指针指向他本身
- 当我们向对象发送消息时,可以根据isa指针指向寻找原类的方法列表是否存在这个消息,确定是否可以响应方法,作用就是帮我们寻找方法
四、objc对象的类方法和实例方法有什么本质区别和联系?
- 区别:
-
属于谁
类方法属于类对象 [NSString stringwithFormat:]
实例方法属于实例对象 [str length] -
谁调用
类方法 类对象调用
实例方法 实例对象调用 -
self是什么
在类方法里面,self表示类对象
在实例方法里,self表示实例对象 -
是否可以访问成员变量
类方法里 不可以访问成员变量
实例方法 可以访问成员变量 -
方法调用问题
类方法里 可以调用实例方法也可以调用类方法
实例方法里 继可以调用实例方法也可以调用类方法