1、 OC代码编译过程
从图可看出
1、Objective-C代码,底层实现其实都是C\C++代码
2、Objective-C的类都是基于C\C++的数据结构实现的。
2、Main文件写的源码如下
•在Main文件里面新建了HPStudent类,HPPerson类。HPStudent继承HPPerson.
•在编译生成的cpp文件中看下我们的类到底变成什么样子了?
•Objective-C代码转换为C\C++代码,然后看下OC类到底变成啥样子。
•命令:xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
3、查看cpp文件源码, HPStudent类的结构
里面有一个结构体structHPPerson_IMPL变量NSObject_IVARS,还有成员变量_no
4、HPPerson类结构
5、 NSObject类结构
6、 获取内存分配大小的函数
•1、运算符:sizeof(obj) ,运算obj指针需要的内存大小
•2、class_getInstanceSize(class)获取某个类需要的内存大小。需要导入#import <objc/runtime.h>
•3、malloc_size(const void *ptr);获取某个指针指向的内存空间实际分配的内存大小。
需要导入:import <malloc/malloc.h>
7、HPStudent对象内存分配情况
为啥不一样?
•1、sizeof(obj) 运算得到的是obj指针的内存大小,在64位的机器中(比如MAC or iphone),指针的内存大小是8字节。所以打印出8。
•2、class_getInstanceSize得到的是HPStudent实例对象需要的内存大小。那为什么不是8字节指针+int型_no的4字节+_age4字节+_height4字节=20个字节呢?而是24字节?
因为结构体存储尊享内存对齐规则,结构体的对齐值是成员变量内存最大值(默认情况,也可以通过#pragma pack(value)指定其他值)。在Student这个结构体中isa指针占用8字节是最大值,作为对齐值来计算结构体需要的内存大小,也就是8+8+8=24字节。
•3、如果HPPserson的成员变量改成@private。class_getInstanceSize获取的内存大小为啥还是24字节?
改成私有变量也是属于结构体的一部分,从上面Student结构体看出,里面有个Person结构体成员,不管Person结构体内成员变量是什么权限,都需要分配固定内存给 这个结构体也就是Person结构体大小没变化。所以Student的大小也是不变,还是24。
•4、malloc_size获取得到的内存大小为啥是32字节,而不是24呢?
1)mallco_size获取的是对象实际占用的内存大小。那么对象的实例化过程中,核心是调用allocWithZone。这个方法是属于objc库里面的
objc库是开源的:http://opensource.apple.com/tarballs/objc4/
下载后找到NSObject的allocWithZone调用核心是:
里面的核心是调用了calloc\mallco_zone_calloc函数,由于是默认没有指定size内存大小,此处是size=0.
这个底层函数,可以下载源码查看(https://opensource.apple.com/tarballs/libmalloc/)
里面很多calloc分配内存函数,很乱。找资料后面找到NANO_MAX_SIZE这个宏定义。是作为分配内存大小的一个值。
从这个值可以知道,我们手机ios或者mac os系统里面的分配内存是按16的倍数来分配内存大小的。系统分配内存也是遵循内存对齐的规则(提高存储效率),系统相当于把内存按16的倍数切格好一块块的小内存,我们的Student需要的内存是24字节,刚刚好可以分一块32自己的内存给Student的对象。因此Student对象最终分配的内存大小是32。