第一
面试题:一个NSObject对象占用多少内存?
答案:
系统分配了16个字节给NSObject对象
但是NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)
扩展:一个字节由8个二进制位组成
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// OC ==》 C 或者 C++ ==》 汇编语言 ==》 机器语言
// OC 转 C或者C++ 的命令:clang -rewrite-objc main.m -o main.cpp
// OC 对象的实质就是一个结构体,结构体中包含一个isa指正属性,一个指针占用8个字节
NSObject *obj = [[NSObject alloc]init];
// 获取NSObject实例对象的成员变量所占用的大小 >> 8字节
// 实际意义:创建一个实例对象,至少需要多少内存
// getInstanceSize返回的是经过内存对齐的大小
// 结构体内存对齐的规则之一:结构体的大小必须是最大成员大小的倍数
// 备注:内存空间分配是连续的,如果前面成员变量的内存还有未使用的空间则会使用
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
// 获取obj指针所指向内存的大小 >> 16字节
// 实际意义:创建一个实例对象,实际上分配了多少内存
// 分配内存的规则:都是16的倍数
NSLog(@"%zd",malloc_size((__bridge const void *)obj));
// 总结:创建一个NSObject对象,系统分配的内存大小是16个字节,真正使用的内存大小是8个字节
// 并且malloc框架代码中规定如果一个实例对象的大小最小为16个x字节,少于16则自动补足16个字节
}
return 0;
}
扩展问题:一个Person对象、一个Student对象占用多少内存空间?
答案:16个字节、16个字节
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>
@interface Person:NSObject
{
@public
int _age;
}
@end
@implementation Person
@end
@interface Student:Person
{
@public
int _no;
}
@end
@implementation Student
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *obj = [[Student alloc]init];
// '->'代表通过指针的方式直接访问成员变量
// 一个 int 四个字节
obj->_no = 4;
obj->_age = 5;
}
return 0;
}
备注:OC基本数据类型占用的内存大小
/*
32位机器打印结果:
char: 1
int: 4
short:2
long: 4
unsigned int: 4
unsigned short:2
unsigned long: 4
long long: 8
NSInteger: 4
NSUInteger:4
*/
/*
64位机器打印结果:
char: 1
int: 4
short:2
long: 8
unsigned int: 4
unsigned short:2
unsigned long: 8
long long: 8
NSInteger: 8
NSUInteger:8
*/
第二
Object-C中的对象,简称OC对象,主要可以分为3种
(1)instance对象(实例对象)
instance对象就是通过alloc出来的对象,每次调用alloc都会产生新的instance对象
instance对象在内存中存储的信息包括:isa指正、其他成员变量(2)class对象(类对象)
class对象在内存中存储的信息包括
a、isa指针
b、superclass指针
c、类的属性信息(@property)、类的对象方法信息(instance method)
d、类的协议信息(protocol)、类的成员变量信息(var)
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 实例对象
NSObject *object1 = [[NSObject alloc]init];
// 类对象(一个类的类对象,在内存中只有一份,所以下面三个类对象实则都是指向同一个内存)
// class方法返回的一直都是class对象
// 方法一
Class objectClass1 = [object1 class];
// 方法二
Class objectClass2 = object_getClass(object1);
// 方法三
Class objectClass3 = [NSObject class];
}
return 0;
}
(3)meta-class对象(元类对象)
元类对象在内存中存储的信息包括
每个类在内存中有且只有一个meta-class对象
a、isa指针
b、superclass指针
c、类的类方法信息(class method)
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 实例对象
NSObject *object1 = [[NSObject alloc]init];
// 类对象
Class objectClass = object_getClass(object1);
// 元类对象
Class objectMetaClass = object_getClass(objectClass);
}
return 0;
}
扩展知识:
1、Class objc_getClass(const char *aClassName)
传入字符串类名,返回对应的类对象
2、Class object_getClass(id obj)
传入obj可能是instance对象、class对象、meta-class对象
返回值:
a、如果是instance对象,返回class对象
b、如果是class对象,返回meta-class对象
c、如果是meta-class对象,返回NSObject(基类)的meta-class对象
3、-(Class)class、+(Class)class
返回的就是类对象
网友评论