小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
1.1 sizeof
sizeof不是函数,而是一个操作符- 一般会传入数据类型,编译器在编译时期即可确定大小
sizeof得到的大小,即是该类型占用的空间大小
1.2 class_getInstanceSize
class_getInstanceSize是runtime提供的api- 作用:获取类的实例对象所占用的内存大小
- 本质:获取实例对象中成员变量的内存大小
- 采用8字节对齐,参照对象的属性大小
1.3 malloc_size
- 作用:获取系统实际分配的内存大小
- 采用16字节对齐,参照整个对象的大小
- 实际分配的内存大小,必须是
16的整数倍
具体案例分析
打开LGPerson.h文件,写入以下代码:
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;
@end
打开main.m文件,写入以下代码:
#import <Foundation/Foundation.h>
#import "LGPerson.h"
#import <objc/runtime.h>
#import <malloc/malloc.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
LGPerson *person = [LGPerson alloc];
NSLog(@"sizeof:%lu",sizeof(person));
NSLog(@"class_getInstanceSize:%lu",class_getInstanceSize([LGPerson class]));
NSLog(@"malloc_size:%lu",malloc_size((__bridge const void *)(person)));
}
return 0;
}
-------------------------
//打印结果:
sizeof:8
class_getInstanceSize:40
malloc_size:48
- sizeof为8,因为
person对象,本质是指针地址,占8字节 - class_getInstanceSize为40,
LGPerson的成员变量大小为36字节,8字节对齐后占40字节 - malloc_size为48,系统分配的内存大小,经过
16字节对齐后,占48字节
扩展
在LGPerson中,即是没有任何成员变量,class_getInstanceSize依然会占8字节,因为LGPerson继承自NSObject,默认存在isa成员变量
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
isa为Class类型,本质是objc_class类型的结构体指针,占8字节
typedef struct objc_class *Class;
objc_class继承自最原始的objc_object结构体
struct objc_class : objc_object {
objc_class(const objc_class&) = delete;
objc_class(objc_class&&) = delete;
void operator=(const objc_class&) = delete;
void operator=(objc_class&&) = delete;
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
...
};
找到objc_object结构体,只有一个成员变量isa
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
所以,万物皆对象,万物皆有isa。