我们平时编写的Objective-C代码,底层实现其实都是C/C++代码
所以Objective-C的面向对象都是基于C/C++的数据结构实现的。
Objective-C的对象、类是基于C/C++的结构体数据结构实现的。
将Objective-C代码转换为C/C++代码(需要用到clang编译器)
在终端一直cd到想要转为cpp文件的所在位置,然后敲命令行
clang -rewrite-objc main.m -o main.cpp
将main.m文件转为main.cpp文件,因为平台不同支持的代码肯定不一样,例:windows、Mac、iOS等,这里主要讨论iOS平台,所以用如下命令行
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
NSObject的底层实现
Class isa
里边的Class是一个指向结构体的指针。
runtime里边有一个获取实例实际大小的方法,如下
#import <objc/runtime.h>
NSObject *obj = [[NSObject alloc] init];
//获得NSObject实例对象的成员变量所占用的大小 >> 8
num = class_getInstanceSize([NSObject class]);
NSLog(@"%zd",num);//无符号的打印方式
打印结果为8
malloc里边有一个获取开辟内存大小的方法,如下
#import <malloc/malloc.h>
NSObject *obj = [[NSObject alloc] init];
//获得obj指针所指向内存的大小>>16
num = malloc_size((__bridge const void *)obj);
NSLog(@"%zd",num);
打印结果为16
一个NSObject对象占用多少内存?
系统分配了16个字节给NSObject对象(通过malloc_size函数获得),但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)
NSObject *obj = [[NSObject alloc] init];
下断点,然后实时查看内存数据
实时查看内存数据方法:
Debug-> Debug Workflow -> View Memory (Shift + Command + M)
也可用lldb指令查看内存:
常用lldb指令
print、p
:打印
po
:打印对象
-
读取内存:
memory read/数量格式字节数 内存地址
x/数量格式字节数 内存地址 -
修改内存中的值
memory write 内存地址 数值
memory write 0x0000010 10 -
格式
x是16进制,f是浮点,d是10进制 -
字节大小
b:byte 1字节,h:half word 2字节
w:word 4字节,g:giant word 8字节
现在研究一下自定义的对象(有新的成员属性)占用的内存
在main.m文件中新建一个继承NSObject的Student类,然后写两个int类型的成员变量,再把main.m文件转成c++文件
@interface Student : NSObject
{
@public
int _no;
int _age;
}
@end
@implementation Student
@end
Student *student = [[Student alloc] init];
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
在cpp文件中发现
struct NSObject_IMPL{
Class isa;
}
struct Student_IMPL{
struct NSObject_IMPL NSObject_IVARS;
int _no;
int _age;
};
Student *student = [[Student alloc] init];
student->_no = 4;
student->_age = 5;
NSLog(@"%zd",class_getInstanceSize([Student class]));//16
NSLog(@"%zd",malloc_size((__bridge const void *)student));//16
再用实时查看内存数据的方法去查看,先在lldb中打印出student的首地址,
p student
,然后把对象的首地址在debug -> debug workflow -> view memory中显示内存数据。如下图:大端小端模式:
思考:一个Person对象、一个Student对象占用多少内存空间?
@interface Person : NSObject
{
@public
int _age;
}
@end
@implementation Person
@end
@interface Student : Person{
@public
int _no;
}
@end
@implementation Student
@end
Person *person = [[Person alloc] init];
Student *stu = [[Student alloc] init];
NSLog(@"Person -- %zd",class_getInstanceSize([Person class]));//16 class_getInstanceSize内存对齐过的占用的大小
NSLog(@"Person -- %zd",malloc_size((__bridge const void *)person));//16
NSLog(@"Student -- %zd",class_getInstanceSize([Student class]));//16
NSLog(@"Student -- %zd",malloc_size((__bridge const void *)stu));//16
方法不在实例对象内存里边,所以方法不占用内存,只有成员变量和属性影响内存的大小。方法放在什么地方???(后边研究再补充:类对象的方法列表里边)
2个容易混淆的函数
- 创建一个实例对象,至少需要多少内存?
#import <objc/runtime.h>
class_getInstanceSize([NSObject class])
- 创建一个实例对象,实际上分配了多少内存?
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);
网友评论