OC对象的本质

作者: MR_詹 | 来源:发表于2019-08-27 17:43 被阅读0次

第一

面试题:一个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
      返回的就是类对象

相关文章

网友评论

    本文标题:OC对象的本质

    本文链接:https://www.haomeiwen.com/subject/oxqyectx.html