OC

OC对象的本质

Posted on 2020-12-15,3 min read

简单了解NSObject的‘底层实现’、‘占用内存’及‘分类’。

NSObject的底层实现

oc中

@interface NSObject {
    Class isa;
}
@end

转为c++后 (64位系统中占8个字节,32位系统中占4个字节,以下均以64位系统为例)

struct NSObject_IMPL {
    Class isa; // 占8个字节
};

Class实际上是一个指针

typedef struct objc_class *Class; 

一个NSObject对象占多少内存?

从上面的NSObject底层实现看,既然NSObject的对象本质上是一个isa的Class指针,而Class又占用8个字节,那么一个NSObject对象是不是就占用8个字节呢?实际上不是,一个NSObject实际上占用16个字节。
alloc本质是在调用allocWithZone,其函数内部在分配内存时,会判断if( size < 16 ){size = 16},

总结:系统分配了16个字节给NSObject对象,但NSObject对象内部只使用了8个字节的空间(64bit环境下)。

NSObject *obj = [[NSObject alloc] init];
// 获得NSObject实例对象的 “成员变量” 所占用的大小(基于内存对齐原则,最大成员内存的倍数)
NSLog(@"%zd", class_getInstanceSize([NSObject class])); // 8
// 获得obj指针所指向的内存大小(16的倍数)
NSLog(@"%zd", malloc_size((__bridge const void *)obj)); // 16

OC对象的分类

  • instance对象(实例对象)
    NSObject *object = [[NSObject alloc] init];
    
  • class对象(类对象)
    每个类在内存中有且只有一个class对象
    Class objectClass1 = [object class];
    Class objectClass2 = object_getClass(object);
    // -(void)test; 方法是保存在类对象里的
    
  • meta-class对象(元类对象)
    每个类在内存中有且只有一个meta-class对象
     #import <objc/runtime.h>
    // 将类对象传入,获得元类对象(如果传入instance实例对象,则返回的是class对象)
    Class objectMetaClass = object_getClass(objectClass); // 元类对象
    Class objectClass2 = object_getClass(object); // 类对象
    // +(void)test; 类方法是保存在元类对象里的
    

object_getClass:

Class object_getClass(id obj){
    // 如果是instance对象,返回class对象;
    // 如果是class对象,返回meta-class对象
    // 如果是meta-class对象,返回NSobject(基类)的meta-class对象;
    if (obj) return obj->getIsa();
    else return Nil;
}

下一篇: HTTP相关知识点→

loading...