OC对象的本质
Objective-C的面向对象都是基于C/C++的数据结构实现的,而后者又是基于结构体实现的,所以OC转换的最终顺序:
Objective-C -> C/C++ -> 汇编语言 -> 机器语言
创建一个OC的项目,main.m中代码如下:
#import <Foundation/Foundation.h> @interface Person : NSObject { @public int _age; int _no; } @end @implementation Person @end int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [[Person alloc] init]; person->_age = 10; person->_no = 20; int temp = 10; NSLog(@"%zd", class_getInstanceSize([Person class])); NSLog(@"%zd",malloc_size((__bridge const void *)(person))); NSLog(@"%zd", sizeof(temp)); } return 0; }
运用指令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp 将main.m文件转化为c++文件
可得到如下代码:
struct Person_IMPL { struct NSObject_IMPL NSObject_IVARS; int _age; int _no; };
其实可以看出类Person被转成Person_IMPL的结构体:
可以用如下的代码完成等价实现:
#import <Foundation/Foundation.h> #import <malloc/malloc.h> #import <objc/runtime.h> struct NSObject_IMPL { Class isa; }; struct Person_IMPL { struct NSObject_IMPL NSObject_IVARS; int _age; int _no; }; @interface Person : NSObject { @public int _age; int _no; } @end @implementation Person @end int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [[Person alloc] init]; person->_age = 10; person->_no = 20; int temp = 10; NSLog(@"%zd", class_getInstanceSize([Person class])); NSLog(@"%zd",malloc_size((__bridge const void *)(person))); NSLog(@"%zd", sizeof(temp)); struct Person_IMPL *peoImpl = (__bridge struct Person_IMPL *)(person); NSLog(@"no is %d, age is %d", peoImpl->_no, peoImpl->_age); } return 0; }
打印结果如下:
OC对象的本质[13731:471379] 16 OC对象的本质[13731:471379] 16 OC对象的本质[13731:471379] 4 OC对象的本质[13731:471379] no is 20, age is 10
整个person对象分配了16个字节,而且该对象实际使用也是16个字节,而int是四个字节,也就是说NSObject_IMPL是8个字节
关于转换cpp文件的指令的详解:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp xcrun xcode run -sdk 具体哪种设备 -arch 哪种架构