自定义类的内存本质
自定义一个student 类
@interface Student : NSObject {
@public
int _age;
int _height;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu->_age = 7;
stu->_height = 15;
}
return 0;
}
将Objective-c代码转换成 C\C++的代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
找到Student 的 C++实现
struct Student_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _no;
int _age;
};
NSObject_IMPL的 C++实现
struct NSObject_IMPL {
Class isa;
};
Class 的C++实现
typedef struct objc_class *Class;
由于NSObject_IMPL
结构体只有一个class
类型的 isa 成员,Student_IMPL
可以简化成
struct Student_IMPL {
Class isa;
int _no;
int _age;
};
Student_IMPL内存结构
假设 isa
的地址是0x100400110,class 是指向结构体的指针,内存大小8个字节,int 在64bit 内存大小是4个字节,所以初步得出
初步结论:Student的对象占用内存大小16个字节
现在用class_getInstanceSize
和malloc_size
两个方法来打印下返回大小
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu->_no = 4;
stu->_age = 5;
NSLog(@"%zd", class_getInstanceSize([Student class]));
NSLog(@"%zd", malloc_size((__bridge const void *)stu));
}
return 0;
}
打印结果
打印结果都是16,与结论相同。
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
stu->_no = 4;
stu->_age = 5;
// NSLog(@"%zd", class_getInstanceSize([Student class]));
//
// NSLog(@"%zd", malloc_size((__bridge const void *)stu));
struct Student_IMPL *studentImpl = (__bridge struct Student_IMPL *)stu;
NSLog(@"no---%d; age-----%d", studentImpl->_no, studentImpl->_age);
}
return 0;
}
打印结果
我们把Student
类的对象stu
强制转换成Student_IMPL
结构体类型studentImpl
,打印studentImpl
结构体的成员_no
和_age
,打印结果也正好是4和5,这也侧面验证了Student
类的 C++实现就是Student_IMPL
结构体类型。
现在我们用View Memory工具来查看下stu
的内存情况
内存情况
可以看到0x100417c08
是04,0x100417c0c
是05,也就是_no和_age 的值。
修改0x100417c08
为8,stu
的_no
的值也变成了8
自定义一个person 类和一个继承 person 类的 student 类
@interface Person : NSObject {
int _age;
}
@end
@implementation Person
@end
@interface Student : Person {
int _no;
}
@end
@implementation Student
@end
将Objective-c代码转换成 C\C++的代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
找到相应的 C\C++的代码得实现
struct NSObject_IMPL {
Class isa;
};
struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _age;
};
struct Student_IMPL {
struct Person_IMPL Person_IVARS;
int _no;
};
大致猜测Person
类的对象占用16个字节实际只用了12个字节。我们来打印验证一下
看到class_getInstanceSize
方法打印结果有差异,具体来看看class_getInstanceSize
的源代码
alignedInstanceSize
看到
word_align()
方法,意思就是要按字节对齐。
内存对齐:结构体的大小必须是最大成员大小的倍数
再来看Person
类的 C++实现,最大成员变量isa
是8个字节,所以大于12的最小倍数就是16,也就是class_getInstanceSize
返回16。
大致猜测Student
类的对象占用16个字节实际使用了16个字节。我们来打印验证一下
网友评论