OC笔记 - 对象的本质


前言

1 - iOS中的 OC代码,底层是由 C/C++编写的,OC面向对象也是基于 C/C++的数据结构实现的:OC --> C/C++ --> 汇编语言 --> 机器语言

NSObject对象本质

1 - NSObject对象是一个结构体,里面只有一个成员变量 isa

 1 #import 
 2 
 3 // 底层实现:其实是 C++结构体
 4 struct NSObject_IMPL {
 5     Class isa;
 6 };
 7 
 8 int main(int argc, const char * argv[]) {
 9     
10     // 声明一个 NSObject对象
11     NSObject *obj = [[NSObject alloc] init];
12     return 0;
13     
14 }

解析图示:我们声明的指针变量 obj指向对象的地址其实就是 isa指针的地址,实际占 8个字节,但是系统默认分配 16个字节大小

OC对象本质

1 - 先看代码:在 main.m文件中声明并实现 Student

 1 #import 
 2 // 底层实现
 3 struct Student_IMPL{
 4   
 5     // 实际上 Student对象转换成 C++结构体是这个样子
 6     // struct NSObject_IMPL NSObject_IVARS;// 我们知道 NSObject_IMPL中其实就是一个 isa指针
 7     // 所以可简化成
 8     Class isa;
 9     
10     // 实例变量
11     int _no;
12     int _age;
13     
14 };
15 
16 @interface Student : NSObject{
17     @public
18     int _no;
19     int _age;
20 }
21 
22 @end
23 
24 @implementation Student
25 
26 @end
27 
28 int main(int argc, const char * argv[]) {
29     
30     Student *stu = [[Student alloc] init];
31     stu->_no = 4;
32     stu->_age = 5;
33     
34     // 验证底层实现是否正确
35     // 把 stu对象强转成结构体:OC转换成 C/C++ 有时需要使用 __bridge关键字
36     struct Student_IMPL *stuImpl = (__bridge struct Student_IMPL *)stu;
37     NSLog(@"%d  %d",stuImpl->_no,stuImpl->_age); // 4   5
38 
39     return 0;
40     
41 }

图示

2 - 有这么两个类,请问在 64位环境下一个 Person对象、Student对象各占多少内存空间

实际上 Person对象内存大小 = size( NSObject对象) + size(_age) = 8 + 4 =12;Student对象内存大小 = size( Person对象) + size(_no) = 12 + 4 = 16      

但是有内存对齐的缘故,系统最终会给 NSObject对象分配 16个字节,多出 8个未使用的字节空间用来存储 _age,Person对象最终得到的分配空间是 16字节

同样 Student对象中的 Person对象(16 字节)还剩 16 - size(isa) - size(_age) = 4 字节,刚好用来存放 _no,所以 Student对象最终得到分配的空间也是 16字节

class_getInstanceSize | malloc_size

1 - class_getInstanceSize:计算对象实际内存大小;malloc_size 计算系统为对象分配的内存大小

#import 
#import 
#import 

int main(int argc, const char * argv[]) {
    
    NSObject *objc = [NSObject new];
    
    NSLog(@"%zd",class_getInstanceSize([objc class])); // 8
    NSLog(@"%zd",malloc_size(objc)); // 16
    return 0;
    
}