iOS底层原理--OC对象的本质

哇哦~距离上次更新笔记已是long long age 唔~ 为了颜值与技术在线,坚持写笔记,坚持瘦回两位数(emm…貌似暴露了什么)

算春长不老,人愁春老,愁只是,人间有.png

1、NSObject的本质是什么?

分析: OC代码的底层实现实质是C/C++代码,继而编译成汇编代码,最终变成机器语言。 打开终端,进入main.m所在的文件夹,通过clang rewirte-objc main.m -o main.cppxcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 代码,生成cpp文件。 在cpp文件中找到如下代码:

struct NSObject_IMPL {
    Class isa;
}

NSObject的底层实现实质是一个结构体。而结构体中的成员isa是Class类型,通过源码typedef struct objc_class *Class可知它是一个指针。在64为环境下指针占8个字节,而在32位机下是占4个字节。因此该结构体占8个字节(因为该结构体只有一个成员)。

2、NSObject对象占多少内存?

分析: 通过打印

NSObject *obj = [[NSObject alloc]init];
NSLog(@"%zd",malloc_size((__bridge const void *)obj));

可知NSObject对象占16个字节。 那么与题1所述结构体中占8个字节是否冲突? 通过打印NSLog(@"%zd",class_getInstanceSize([NSObject class]))获取NSObject类的实例对象的成员变量所占用的(内存对齐之后)大小,显示确实为8个字节。 在objc的源码中找到class_getInstanceSize方法,发现它返回的是cls->alignedInstanceSize(),对它的描述为Class's ivar size rounded up to a pointer-size boundary意指返回成员变量占据的大小。因此创建一个NSObject对象需要分配16个字节,只是真正利用的只有8个字节,即isa这个成员的大小。 事实上,查看allocWithZone的源码发现它最底层的创建实例的方法实际上是调用了C语言的calloc方法,在该方法中,规定若分配的字节不满16将把它分配为16个字节。

3、若一个Student类继承自NSObject类,那么Student类的对象占多少内存?

分析: 新建Student类,添加成员变量。通过clang反编译,打开cpp文件找到Student类的底层实现。

struct Student IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    // 还有Student类的成员变量
    //……
}

从这段代码可以看出,若一个类继承自另一个类,则它的底层会将父类的成员变量放在结构体的最前面,此后依次放置本类的成员变量。而从之前的分析可知,NSObject_IMPL的本质就是一个装有成员变量isa的结构体,因此,Student类对象所占的内存为isa的内存8加上Student类成员变量所占的空间。若不满16个字节,会强制分配到16个字节。另,由于<u>内存对齐</u>的规定,结构体的最终大小必须是最大成员的倍数。

#import <malloc/malloc.h>
@interface Student:NSObject{
   @public
    int age;
    int no;
    int address;
    NSString *name;
    NSString *name2;
    
}
@end

@implementation Student

@end


int main(int argc, char * argv[]) {
    @autoreleasepool {
        Student *stu = [[Student alloc]init];
        NSLog(@"%zd",malloc_size((__bridge const void *)stu));
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

打印结果如下图所示:

结果

附:苹果官方开放源码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券