美文网首页
自定义类的内存占用

自定义类的内存占用

作者: 孙国立 | 来源:发表于2021-02-22 11:51 被阅读0次

    演示代码1

    默认为arm64

    #import <Foundation/Foundation.h>
    #import <objc/runtime.h>
    #import <malloc/malloc.h>
    
    
    @interface Student : NSObject
    {
        @public
        int _age;
        int _sex;
    }
    @end
    @implementation Student
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            Student *student = [[Student alloc] init];
            NSLog(@"%zu",class_getInstanceSize([Student class]));
            NSLog(@"%zu",malloc_size((__bridge const void *)student));
        }
        return 0;
    }
    //打印结果为 16  16
    
    • OC代码转化成C++的代码
      将代码转化成C++的代码会找到如下的代码块
    struct Student_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
        int _age;
        int _sex;
    };
    

    代码块中有agesexNSObject_IMPL这三个属性。agesex的类型是int类型,所以每个占用4个字节的内存,而NSObject_IMPL占用的是8个字节。合起来就是16个字节。而alloc方法返回的最小的内存大小也是16所以两个方法返回的内存大小都是16

    演示代码2

    @interface Person : NSObject
    {
        int _sex;
    }
    @end
    
    @implementation Person
    @end
    
    @interface Student : Person
    {
        @public
        int _age;
    }
    @end
    
    @implementation Student
    
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            Person *person = [[Person alloc] init];
            NSLog(@"%zu",class_getInstanceSize([Person class]));
            NSLog(@"%zu",malloc_size((__bridge const void *)person));
            
            Student *student = [[Student alloc] init];
            NSLog(@"%zu",class_getInstanceSize([Student class]));
            NSLog(@"%zu",malloc_size((__bridge const void *)student));
            
        }
        return 0;
    }
    //打印结果为 16 16 16 16
    
    • Person类的内存占用
      OC转化成C++
    struct Person_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
        int _sex;
    };
    

    为什么class_getInstanceSize返回的大小是16
    NSobject内存占用这个文章中讲到过NSObject实际上里面只有一个isa指针参数,占用8个字节的内存,而sexint类型占用4个字节的内存,加起来一共是12个字节,而class_getInstanceSize方法返回的是实例对象占用的内存大小,应该是12个字节才对。呢这里为什么返回的是16

    • 内存补齐
      返回的内存大小是成员变量中占用内存最大的呢个成员变量的倍数Person类中占用内存最大的成员变量是isa占用8个字节的内存,根据内存补齐的原则应该返回的是8的倍数,所以最少是16
    • class_getInstanceSize的实现方法给到了明确的说法
    uint32_t alignedInstanceSize() const {
            return word_align(unalignedInstanceSize());
        }
    

    word_align方法中调用了这么一个方法,align是补齐的意思,也就是说他做内存补齐。而上面已经说到了内存补齐的具体计算方法。所以这里返回的成员变量的内存大小是做了内存补齐后的大小,因此是16

    • Student类的内存占用
      OC转化成C++
    struct Student_IMPL {
        struct Person_IMPL Person_IVARS;
        int _age;
    };
    

    在上面已经说过了Person类返回的内存大小是16Student类中又新添加了一个成员变量age,按理来说应该返回的是20,然后内存对齐一下返回的应该是32才对的。呢这里为什么返回16了呢。
    首先Person类分配了16个内存空间,但是isasex属性只占用了12个字节的内存空间,还剩下4个字节的内存空间。刚好分配给age属性使用,所以返回的结果就是16而不是32

    补充说明
    @interface Student : NSObject
    {
        @public
        int _age;
        int _sex;
        NSString *name;
    }
    

    如果像上面这样的话内存占用应该是多少呢。按照前面所说的东西来总结的话应该是24。但是实际的返回确实32。关于这个问题我有查询过源码的东西,但因为自己的技术水平有限在解析源码的时候走到一定的程度发现无法在往下去查看了。并没有找到完整的逻辑。但是我在网上查询了一下相关的资料。发现计算机中也存在着内存对齐的问题,也就是说返回的内存块的大小只能是16、32、64......这样的

    相关文章

      网友评论

          本文标题:自定义类的内存占用

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