OC的代码基于C/C++ 实现的,所以我们可以将OC代码转换成C++ 代码查看NSObject在C++ 中的实现。
转换命令:
xcrun -sdk iphoneos clang -arch arm64 main.m -rewrite-objc -o main.cpp
xcrun: xcode commendline run
参数sdk 指定iphoneos系统
clang 编译器
参数arch指定arm64 CPU架构版本
rewrite-objc 重写OC的代码
参数o 指定生成的文件名,不指定则默认和原文件同名
NSObject
查看生成的cpp文件,发现NSObject对象的结构体
定义如下:
struct NSObject_IMPL {
Class isa;
};
分析:isa为指针,指针类型(64位系统中)占8字节。
NSObject类结构体需要8字节内存,由于runtime系统设计的限制--初始化对象最少16字节,所以NSObject结构体实际需要占用16字节。
查看源码中的定义
size_t instanceSize(size_t extraBytes) {
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
自定义类
@interface Person : NSObject
{
@public
double _weight;
int _age;
}
@end
@implementation Person
@end
struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS;//Class isa;
double _weight;
int _age;
};
分析:isa为指针,指针类型(64位系统中)占8字节,int类型占4字节,double类型指针占8字节。
所以person类结构体需要20字节内存,由于结构需要进行字节对齐(以最大成员变量的内存数为单位,此处单位为8字节),所以person结构体实际需要占用24字节。
验证方法
1、class_getInstanceSize
函数获取成员变量大小
malloc_size
获取对象分配的内存(内存对齐的缘故,16的倍数,所以person实例对象实际分配了32字节)
NSLog(@"%zu",class_getInstanceSize([Person class]));
Person *p = [[Person alloc] init];
NSLog(@"%zd",malloc_size((__bridge void *)p));
2、转换成结构体验证
struct Person_IMPL {
Class isa;
double _weight;
int _age;
};
Person *p = [[Person alloc] init];
p->_age = 1;
p->_weight = 2;
struct Person_IMPL *s = (__bridge struct Person_IMPL *)p;
NSLog(@"%d -- %f",s->_age,s->_weight);
3、查看内存验证
Xcode中打断点,触发断点,查看person实例对象的内存地址,然后Debug-->Debug WorkFlow-->View Memory
,输入实例对象的内存地址
例如
F9 81 00 00 01 80 1D 00 //isa指针地址
00 00 00 00 00 00 00 40 //weight
01 00 00 00 00 00 00 00 //age
00 00 00 00 00 00 00 00
2D 5B 4E 53....//其他
更复杂的情况
@interface Person : NSObject
@property (nonatomic,assign) double weight;//8
@property (nonatomic,assign) long weight1;//8
@property (nonatomic,assign) float weight2; //4
@property (nonatomic,copy) NSString *name;//8
@property (nonatomic,assign) int age;//4
@property (nonatomic,assign) BOOL sex;//1
@property (nonatomic,assign) char flg;//1
@property (nonatomic,assign) short s;//2
@end
查看生成的结构体如下:
struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS;
BOOL _sex;
char _flg;
short _s;
float _weight2;
int _age;
double _weight;
long _weight1;
NSString *_name;
};
小细节:用@Property声明的属性(Xcode自动帮生成_开头的成员变量),字节低的排前面,相同字节数的变量根据代码顺序排列;自己声明的成员变量,根据代码的顺序进行排列。