OC对象的本质(上):OC对象的底层实现原理

OC对象的本质(上):OC对象的底层实现原理
OC对象的本质(中):OC对象的种类
OC对象的本质(下):详解isa&superclass指针

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

Objective-C的本质

平时我们编写的OC代码,底层实现都是C/C++代码

Objective-C --> C/C++ --> 汇编语言 --> 机器码

所以Objective-C的面向对象都是基于C/C++的数据结构实现的,所以我们可以将Objective-C代码转换成C/C++代码,来研究OC对象的本质。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
    }
    return 0;
}

我们在main函数里面定义一个简单对象,然后通过 clang -rewrite-objc main.m -o main.cpp命令,将main.m文件进行重写,即可转换出对应的C/C++代码。但是可以看到一个问题,就是转换出来的文件过长,将近10w行。

因为不同平台支持的代码不同(Windows/Mac/iOS),那么同样一句OC代码,经过编译,转成C/C++代码,以及最终的汇编码,是不一样的,汇编指令严重依赖平台环境。
我们当前关注iOS开发,所以,我们只需要生成iOS支持的C/C++代码。因此,可以使用如下命令

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc <OC源文件> -o <输出的cpp文件>
-sdk:指定sdk
-arch:指定机器cpu架构(模拟器-i386、32bit、64bit-arm64 )
如果需要链接其他框架,使用-framework参数,比如-framework UIKit
一般我们手机都已经普及arm64,所以这里的架构参数用arm64,生成的cpp代码如下

接下来,我们查看一下main_arm64.cpp源文件,如果熟悉这个文件,你将会发现这么一个结构体

struct NSObject_IMPL {
   
	Class isa;
};

我们再来对比看一下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

简化一下,就是

@interface NSObject  {
   
    Class isa ;
}
@end

是不是猜到点什么了?没错,struct NSObject_IMPL其实就是NSObject的底层结构,或者说底层实现。换个角度理解,可以说C/C++的结构体类型支撑了OC的面相对象。

点进Class的定义,我们可以看到 是typedef struct objc_class *Class;

Class isa; 等价于 struct objc_class *isa;

所以NSObject对象内部就是放了一个名叫isa的指针,指向了一个结构体 struct objc_class

总结一:一个OC对象在内存中是如何布局的?


猜想:NSObject对象的底层就是一个包含了一个指针的结构体,那么它的大小是不是就是8字节(64位下指针类型占8个字节)?
为了验证猜想,我们需要借助runtime提供的一些工具,导入runtime头文件,class_getInstanceSize ()方法可以计算一个类的实例对象所实际需要的的空间大小

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
   
    @autoreleasepool {
   
        NSObject *obj = [[NSObject alloc] init];
        size_t size = class_getInstanceSize([NSObject class]);
        NSLog(@"NSObject对象的大小:%zd",size);
    }
    return 0;
}

结果是

完美验证,it’s over,let’s go home!



等等,就这么简单?确定吗?答案是否定的~~~
介绍另一个库#import <malloc/malloc.h>,其下有个方法 malloc_size(),该函数的参数是一个指针,可以计算所传入指针 所指向内存空间的大小。我们来用一下

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>

int main(int argc, const char * argv[])</
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值