这篇文章主要介绍的是OC对象转成C++语言以及OC对象的内存分配。
1.OC代码如何转成 C++代码,可以通过下面的命令:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
图片如下:
OC代码转成C++代码之后,OC对象在C++里面对应的是一个结构体代码块,OC的成员变量对应的是结构体的成员。
OC代码:
struct NSObject_IMPL
{
Class isa;
};
struct Person_IMP
{
struct NSObject_IMPL NSObject_IVARS;//最大8个字节
int no; //4个字节
}; //内存对齐:结构体的大小必须是最大成员的大小的倍数
@interface Person:NSObject
{
@public
int no;
}
@end
@implementation Person
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person=[Person new];
NSLog(@"======sizeof===%zu",sizeof(person));
NSLog(@"======class_getInstanceSize==%zu",class_getInstanceSize([person class]));
NSLog(@"======malloc_size==%zu",malloc_size((__bridge const void *)(person)));
//OC对象转成结构体对象
struct Person_IMP *person_IMP=(__bridge struct Person_IMP *)person;
NSLog(@"=====person_IMP.no==%d",person_IMP->no);
}
return 0;
}
C++代码:(OC对象转成C++代码)
struct NSObject_IMPL
{
Class isa;
};
struct Person_IMP
{
struct NSObject_IMPL NSObject_IVARS;
int no;
};
OC代码运行结果:
从上面的运行结果可以看出:我的对Person对象的成员变量no赋值20之后,通过把OC代码转成结构体代码之后,通过结构体访问成员变量no的运行结果也是20。
从这里可以看出OC对象确实是转成了结构体(C/C++代码)。
sizeof(var invar)代表的是运算符,返回一个对象或者类型所占内存的字节数(是一个运算符,在编译的时候会直接返回一个常数如果是int类型直接返回4个字节,double类型的话直接返回8个字节)
class_getInstanceSize(var invar) //获取的是NSObject类的实例对象的成员变量的大小(成员变量实际所占用的内存大小)
malloc_size(var invar) //获得obj指针所指向的内存大小。(内存实际分配到的大小,是16的倍数)
面试总结:
一个NSObject对象占用多少内存?
答案:16个字节 。
可以从2个方面回答:
1.系统给NSObject分配了16个字节。(可以通过这个方法来获取内存大小malloc_size())
2.根据计算机内存对齐原则:一个对象所分配的大小是最大内存字节的倍数。(可以通过这个方法获取内存大小class_getInstanceSize())(通过底层源码可以看出,如果NSObject所分配的内存小于16个的话,就直接返回16个字节大小的内存空间。)
源码:
在objc-runtime-new.h文件中可以看
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;
}
注意(在OC中Class isa指针所占的内存大小是8个字节)