美文网首页iOS开发知识点归纳-详细
OC底层学习笔记(1)-NSObiect本质

OC底层学习笔记(1)-NSObiect本质

作者: 打瞌睡de小男孩 | 来源:发表于2019-12-05 08:50 被阅读0次

    注:文章为自己学习李明杰老师的OC底层视频做的随手笔记

    我们平时编写的Objective-C的代码,底层实现都是C/C++来实现的,所以Objective-C的面向对象都是基于C/C++的数据结构来实现的,具体是基于什么来实现的呢?
    NSObject的声明文件可以看到是一个Class的isa属性

    @interface NSObject <NSObject> {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wobjc-interface-ivars"
        Class isa  OBJC_ISA_AVAILABILITY;
    #pragma clang diagnostic pop
    }
    

    然后编译成C++的代码会发现是一个结构体

    struct NSObject_IMPL {
        Class isa;
    };
    

    那么一个NSObject对象占用多少内存呢?
    实际上NSObject对象里面只有一个isa指针,指向一个结构体

    typedef struct objc_class *Class;
    

    一个指针占用8个字节,是不是这个NSObject对象就在内存中占用8个字节呢
    通过malloc的方法获取创建的NSObject的对象指针所指向的内存的大小

            NSObject *obj = [[NSObject alloc] init];
            NSLog(@"%zd",malloc_size((__bridge const void *)obj));
    
    2019-12-04 20:48:49.819768+0800 test1[29620:292876] 16
    

    答案是16个字节
    但是对象里面就一个isa指针,应该是占用8个字节才是对的,同样,用runtime方法验证了,对象的成员变量占用了8个字节,就是这个指针的大小

      NSObject *obj = [[NSObject alloc] init];
    //对象的成员变量占用的大小,j就是这个对象至少需要多大内存
     NSLog(@"%zd",class_getInstanceSize([NSObject class]));
    
    2019-12-04 20:44:25.296641+0800 test1[29566:289914] 8
    

    那为什么给obj对象分配了16个字节呢,实际上查看OC的源码会发现,alloc给对象分配空间的时候,AllocWithZone
    的实现就明白了了


    image.png
    image.png
    image.png
    image.png

    到这里就很明了了,所以一个OC对象至少占用16个字节,实际上alignedInstanceSize()返回的是8个字节,小于16,默认返回最小16
    如果创建一个student的对象,他的本质又是什么呢,
    带有一个age属性的student对象

    @interface students : NSObject{
        int _age;
    
        
    }
    

    编译成C++可以看到

    struct students_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
        int _age;
    };
    

    还是一个结构体,student继承NSObject,第一个就是NSObject的isa指针,父类的成员变量放到前面,自己的放到最后,那么student占用多少个字节,age占用4个字节,isa占用8个,应该是12个,但是运行发现,其实是占用16个,原因是内存对齐的规则:结构体的最终大小必须是最大成员的倍数,isa占用8个字节,所以增加了一个age属性,就占用8*2=16字节,而不是8+4=12字节了

            students *stu = [[students alloc] init];
            //对象的成员变量占用的大小,j就是这个对象至少需要多大内存
            NSLog(@"%zd",class_getInstanceSize([students class]));
            //分配给对象的大小
            NSLog(@"%zd",malloc_size((__bridge const void *)stu));
    
    2019-12-04 21:21:45.602333+0800 test1[29811:309407] 16
    2019-12-04 21:21:45.602937+0800 test1[29811:309407] 16
    

    继续给student增加属性得到验证,两个属性同样还是占用16个字节,说明一个属性时分配的16个字节有4个是空的


    image.png

    继续给对象增加3属性,发现


    image.png

    对象占用24个字节,为什么不是分配24个字节而是32个呢,根据内存对齐,结构体最大的是8,分配24个没问题呀,看明杰老师读源码发现,OC对象的最小大小是16字节,其实也是根据内存对齐,OC创建的对象永远都是16的倍数

    总结
    一个NSObject对象占用多少个内存?
    系统分配了16个字节给NSObject对象,(可以通过malloc_size函数获得)
    但是NSObject对象内部只使用了8个字节的空间(64位环境下,可以通过class_getInstanceSize函数获得)

    相关文章

      网友评论

        本文标题:OC底层学习笔记(1)-NSObiect本质

        本文链接:https://www.haomeiwen.com/subject/ufwhgctx.html