日常收录

iOS 一个OC对象在内存中的布局&&占用多少内存

2020-09-08  本文已影响0人  枫紫_6174

一.先来看看我们平时接触的NSObject

struct NSObject_IMPL {
    Class isa;
};

在64位机中,一个isa占8个字节,在32位机中,一个isa占4个字节(当然苹果后面的机型都是64位的,这里我们着重讲解64位机)

int main(int argc, char * argv[]) {
    
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        //定义一个objc
        NSObject *objc = [[NSObject alloc]init];
        //打印内存
        NSLog(@"tu-%zd",class_getInstanceSize([NSObject class]));
        NSLog(@"tu-%zd",malloc_size((__bridge const void *)(objc)));
    }
    
}
其打印结果为 objc打印结果

看到上面对两个函数的认识,应该知道为什么输出的一个是8,一个是16了吧,当内存申请<16时,在底层分配的时候,系统会默认最低16个字节,系统给objc16个字节,而objc用到的是8个字节(没添加任何成员变量之前)

二.内存对齐

struct Student {
    struct NSObject_IMPL NSOBJECT_IVARS;
};

也就是说,继承关系,子类直接将父类的isa引用进来

@interface Student : NSObject
{
    @public
    int _age;
    int _no;
    int _tc;
}
@end

其底层C++编译结构体就变成了

struct Student {
    struct NSObject_IMPL NSOBJECT_IVARS;
    int _age;
    int _no;
    int _tc;
};

 //定义一个objc
        Student *objc = [[Student alloc]init];
        //打印内存
        NSLog(@"tu-%zd",class_getInstanceSize([Student class]));
        NSLog(@"tu-%zd",malloc_size((__bridge const void *)(objc)));

2020-09-08 12:35:27.158568+0800 OC底层[1549:79836] tu-24
2020-09-08 12:35:27.159046+0800 OC底层[1549:79836] tu-32

由于创建对象的时候,内存是以8对齐,上面我们讲到一个对象里面包含了一个isa占8个字节,对于student来说它有四个成员变量,isa,age,no,tc,共占8+4+4+4=20字节,但是由于内存以8对齐的原因,我们看到的输出是24, 结构体8位对齐

所以class_getInstanceSize在计算实例大小的时候就是24,其白色区域表示空出了四个字节

可以看到,空白的区域为空出了12个字节,总共为32个字节

三.添加属性

@interface Student : NSObject
{
    @public
    int _age;
    int _no;
    int _tc;

}
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSArray *array;
@end

其在底层C++编译就变成了

struct Student {
    struct NSObject_IMPL NSOBJECT_IVARS;
    int _age;
    int _no;
    int _tc;
    NSString _name;
    NSArray _array;
};

默认的会将属性生成的_name添加进结构体中,计算相应的大小

总结:所以在实际计算类的占用空间大小的时候,根据添加的成员变量就可以计算出一个实例占用的内存大小(即计算出结构体的大小24,然后告诉系统,系统调用calloc分配内存的时候按照16对齐原则分配)

上一篇 下一篇

猜你喜欢

热点阅读