OC对象的本质

137 阅读2分钟

一个NSObject对象占用多少内存?

我们平时写的Objective-C代码,底层实现其实都是C\C++代码. 1629daf21d662684

Objective-C的对象、类主要是基于C\C++的什么数据结构实现的?

  • 结构体 将Objective-C代码转换为C\C++代码
xcrun  -sdk  iphoneos  clang  -arch  arm64  -rewrite-objc  OC源文件  -o  输出的CPP文件

如果需要链接其他框架,使用-framework参数。比如-framework UIKit NSObject的底层实现

// OC
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *objc = [[NSObject alloc] init];
        
        NSLog(@"Hello, World!");
    }
    return 0;
}

我们通过命令行将OC的mian.m文件转化为c++文件。

clang -rewrite-objc main.m -o main.cpp // 这种方式没有指定架构例如arm64架构 其中cpp代表(c plus plus)
生成 main.cpp

我们可以指定架构模式的命令行,使用xcode工具 xcrun

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 
生成 main-arm64.cpp 

main-arm64.cpp 文件中搜索NSObjcet,可以找到NSObjcet_IMPL(IMPL代表 implementation 实现)

我们看一下NSObject_IMPL内部

// 对应的C++代码.
// NSObject Implementation
struct NSObject_IMPL {
    Class isa; // 8个字节
};
// 指针 isa本质就是一个指向 objc_class结构体的指针.
typedef struct objc_class *Class;

一个OC对象在内存中是如何布局的。 NSObjcet的底层实现,点击NSObjcet进入发现NSObject的内部实现

@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
    Class isa  OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
@end

转化为c语言其实就是一个结构体

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

系统分配了16个字节给NSObject对象(通过malloc_size函数获得) 但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)

  • 注意:isa的内存地址一直都在对象的起始位置,所以isa 的内存地址就是对象的内存地址,而isa中存放的地址值并不是对象本身的地址,切勿混淆!!!