iOS底层原理探索—OC对象的本质

本文深入探讨了Objective-C(OC)对象的底层实现,从OC代码如何转化为C++,展示了OC对象、类的内存空间分布。OC对象主要分为实例对象、类对象和元类对象,每个都有其特定的内存结构和指针指向。通过实例分析了对象内存分配,包括isa指针和superClass指针的作用,解释了对象在64位环境下占据的内存大小,并介绍了类对象和元类对象的结构及信息存储。此外,文章还讨论了对象方法和类方法的调用路径,以及OC2.0之后的class结构变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在探索OC对象的本质之前,我们要明白Objective-C的代码,底层的实现都是C/C++代码。
OC代码转化过程

而OC中的对象、类则是基于C/C++的结构体来实现的。

我们可以通过将创建好的OC文件,转化成C++文件来看一下OC对象的底层结构。

OC代码转换成C++

通过命令行将OC的main.m文件转换成C++,生成 main.cpp。

   clang -rewrite-objc main.m -o main.cpp 
/***rewrite代表 重写
   *-o代表 输出
   *cpp代表 c++(c plus plus)
**/

需要注意这种方式没有指定运行平台和架构模式,我们可以通过命令行设置参数,来指定运行平台和架构模式

   xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 
/***xcrun代表 xcode
   * iphoneos代表 运行在iPhone上
   *-arch代表 架构模式,arm64参数代表64位的架构模式
**/

生成的main-arm64.cpp 文件就是main.m转换c++后的文件,直接拖拽到工程中,就可以查看底层实现了。我们在main-arm64.cpp 文件中搜索NSObjcet,可以找到NSObjcet_IMPL(IMPL即 implementation 的缩写,代表实现)。

struct NSObject_IMPL {
    Class isa;
};

可以看到,NObject的底层实现就是一个结构体。我们进一步查看Class

typedef struct objc_class *Class;

我们发现Class其实就是一个指针,指向了objc_class类型的结构体。

OC对象内存空间

通过以上探索我们可以得出总结,OC中对象的底层实现都是通过C\C++的结构体实现的。那么一个OC对象占据了多少内存空间呢?下面让我们用代码实际验证一下。
NSObject对象占多少内存空间

通过代码我们创建了一个NSObject对象,分别调用了class_getInstanceSizemalloc_size方法来查看占据的内存空间。我们看到打印输出了8和16,这是怎么回事呢?
我们通过查看OC源码可知,class_getInstanceSize是返回类的成员变量占据内存的大小。而malloc_size是获取obj指针指向内存的大小
我们上文创建的NSObject对象obj的结构体只有一个成员:isa指针,而指针在64位架构中占8个字节,所以第一次打印输出了8。但是系统为obj对象分配了16个字节的内存,第二次打印输出16。
NSObject对象占据内存空间示意图

上图中黄色区域系统为obj对象分配的16个字节的内存,但是obj对象结构体中只有一个isa指针,所以只占据了绿色区域的8个字节。这一点可以通过查看alloc底层源码也可以证实:
alloc源码

通过alloc底层源码可以看到,如果一个对象占据的内存小于16时,则会直接返回16,也就是说,系统在为对象分配内存空间时,最小为16个字节。
至此我们知道了系统在创建一个对象的时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值