oc 对象内存

对象的本质

objc_object结构体,⾥⾯存储isa指针和成员变量的值

class_getInstanceSize:实际占用的内存空间

malloc_size:系统开辟的内存空间

sizeof:变量的内存大小(类即指针大小,结构体即结构体大小)

OSTestObject1 *objc1 = [[OSTestObject1 alloc] init];

 objc1->count=10;

(lldb) x/6gx objc1

0x6000006718a0: 0x0000000101fdc660 0x0000000000000000

0x6000006718b0: 0x0000000000000000 0x000000000000000a

0x6000006718c0: 0x0000000000000000 0x0000000000000000

0x000000000000000a 存count的值

对象⾥⾯存储了⼀个isa指针 + 成员变量的值,isa指针是固定的,占8个字节,所以影响对象内存的只有成员变量(属性会⾃动⽣成带下划线的成员变量)。在对象的内部是以8字节进⾏对⻬的。苹果会⾃动重成员变量的顺序,将占⽤不⾜ 8 字节的成员挨在⼀起,凑满 8 字节,以达到优化内存的⽬的。

isa指针探索

联合体和结构体

结构体(struct)中所有变量是“共存”的,⽽联合体(union)中是各变量是“互斥”的,只能存在⼀个。struct内存空间的分配是粗放的,不管⽤不⽤,全部分配。这样带来的⼀个坏处就是对于内存的消耗要⼤⼀些。但是结构体⾥⾯的数据是完整的。联合体⾥⾯的数据只能存在⼀个,但优点是内存使⽤更为精细灵活,也节省了内存空间。

位域

位域的宽度不能超过前⾯数据类型的最⼤⻓度,⽐如int占4个字节也就是32位,那后⾯的数字就不能超过32。⼀个位域存储在同⼀个字节中,如⼀个字节所剩空间不够存放另⼀位域时,则会从下⼀单元起存放该位域。位域能够节省⼀定的内存空间

[xxx alloc] 最后调用 _class_createInstanceFromZone,查看源码

初始化isa 指针 obj->initIsa(cls);

objc_object::initIsa(Class cls)

{

    initIsa(cls,false,false);

}

是一个 Class 类型 

typedef struct objc_class *Class;

struct objc_class : objc_object

Class是一个对象,因为继承objc_object

objc_object 存在 isa_t isa;

union isa_t {

    isa_t() { }

    isa_t(uintptr_tvalue) :bits(value) { }

    uintptr_tbits;

...

    public:

#if defined(ISA_BITFIELD)

    struct{

        ISA_BITFIELD;  // defined in isa.h

    };

...

#endif

}

ISA_BITFIELD分平台的

arm64 (真机) 位域

uintptr_t nonpointer : 1;

uintptr_t has_assoc : 1;

uintptr_t has_cxx_dtor : 1;

uintptr_t shiftcls : 33;

uintptr_t magic : 6;

uintptr_t weakly_referenced : 1;

uintptr_t unused : 1;

uintptr_t has_sidetable_rc : 1;

uintptr_t extra_rc : 19

isa_t联合体大小是8个字节

nonPointerIsa

nonPointerIsa是内存优化的⼀种⼿段。isa是⼀个Class类型的结构体指针,占8个字节,主要是⽤来存内存地址的。但是8个字节意味着它就有8*8=64位。存储地址根本不需要这么多的内存空间。⽽且每个对象都有个isa指针,这样就浪费了内存。所以苹果就把和对象⼀些息息相关的东⻄,存在了这块内存空间⾥⾯。这种isa指针就叫nonPointerIsa。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容