NSObject *obj = [[NSObject alloc]init];
获取obj指针所指向内存的大小
NSLog(@"%zd",malloc_size((__bridge const void *)(obj))); 打印得出结果为16
通过查看苹果源码得知苹果默认给NSObject 分配16个字节 如果小于16也就将默认值赋给它
iOS创建对象都是以16的倍数内存对齐
16的由来查看苹果源码得知
inline size_t instanceSize(size_t extraBytes) const {
if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
return cache.fastInstanceSize(extraBytes);
}
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
获取NSObject实例对象的成员变量所占用的大小
NSLog(@"%zd",class_getInstanceSize([NSObject class]));打印得出结果为8
通过查看苹果源码得知 class_getInstanceSize底层实现
size_t class_getInstanceSize(Class cls)
{
if (!cls) return 0;
return cls->alignedInstanceSize();
}
// Class's ivar size rounded up to a pointer-size boundary. 返回实例对象的成员变量所占用的大小
uint32_t alignedInstanceSize() const {
return word_align(unalignedInstanceSize());
}
接下来可以查看NSObject的定义
@interface NSObject <NSObject> {
Class isa ;
}
因为NSObject第一个成员变量就是isa 类型为指针 默认占8字节
// 上述代码NSObject底层实现代码
struct NSObject_IMPL{
Class isa;
}
点击 Class isa 可以查看到是 typedef struct objc_class *Class; 类型
返回是个结构体指针 而结构体也就这么一个成员 所以也就证明了为什么
NSLog(@"%zd",class_getInstanceSize([NSObject class]));打印得出结果为8 指针在64位环境下占8个字节
class_getInstanceSize是实例对象需要多少存储空间。 malloc_size 是给了实例对象多少存储空间也就是实际分配的存储空间
malloc_size的值 = class_getInstanceSize的值+16的倍数
如果打印 class_getInstanceSize = 24
那么 malloc_size 就= 32;因为24以大于16但为了内存对齐所以会取16的倍数也就是32
class_getInstanceSize成员变量只有3个int型的话打印出的值会=24 也许有人会问不是20么 3*4 =12;
12 + 8 = 20才对啊
其实 class_getInstanceSize也会以最大的倍数8 内存对齐来取值 8的由来便是isa指针的值
综上所述得知系统分配了16个字节给NSObject 对象 但NSObject对象内部只用了8个字节的空间来装isa
(在64位的环境下)
网友评论