美文网首页
iOS学习-OC对象的本质 01

iOS学习-OC对象的本质 01

作者: 快乐的tomato | 来源:发表于2020-05-28 14:11 被阅读0次

    先看1个问题

    1、一个NSObject对象占用多少内存?

    一、NSObject 类

    oc代码的底层是C/C++代码
    oc的面向对象其实都是基于C/C++的数据结构实现的:


    image.png

    怎么将oc代码转换为C/C++代码?
    转成iOS平台的代码

    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc oc源文件 -o 输出的cpp文件
    

    转换一下main.m文件
    1、打开终端,cd 到main.md的文件所在文件夹
    2、运行命令 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp


    image.png

    最后生成一个.cpp文件


    image.png

    main函数变成了下面的代码

    int main(int argc, char * argv[]) {
        NSString * appDelegateClassName;
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
    
            appDelegateClassName = NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")));
    
    
            NSObject *obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
     
        }
        return UIApplicationMain(argc, argv, __null, appDelegateClassName);
    }
    

    也可以直接点进去看

    @interface NSObject <NSObject> {
        Class isa  OBJC_ISA_AVAILABILITY;
    }
    

    所以 [[NSObject alloc] init] 底层实现是长得这样子,就是一个结构体,一个结构体里就只有一个指针,所以占8个字节

    struct NSObject_IMPL {
        Class isa;//占8个字节
    };
    
    

    图示


    image.png
    二、自定义的类

    -如果是一个自定义的类Student

    #import <objc/runtime.h>
    #import <malloc/malloc.h>
    @interface Student : NSObject
    {
        @public
        int _no;//4
        int _age;//4
        int _grade;//4
    }8+12=20    24
    多出来的4个字节,好像是计算机内存对齐产生的
    @end
    @implementation Student
    @end
    int main(int argc, char * argv[]) {
        NSString * appDelegateClassName;
        @autoreleasepool {
            
            appDelegateClassName = NSStringFromClass([AppDelegate class]);
            
            Student *xiaoming = [[Student alloc] init];
            xiaoming->_age = 4;
            xiaoming->_no = 5;
            xiaoming->_grade = 98;
           
    
            NSLog(@"Student类实例对象的成员变量所占用的大小:🍎%zd",class_getInstanceSize([Student class]));
            NSLog(@"xiaoming指针所指向内存的大小:🍎%zd",malloc_size((__bridge const void *)(xiaoming)));
            
        }
        return UIApplicationMain(argc, argv, nil, appDelegateClassName);
    }
    
    
    image.png

    又加了几个成员变量,打出的结果不一样

    student对象的本质.png

    假如一个Person对象继承自NSobject,Student 继承自Person,那么Person 和Student分别占用的内存是多少?


    image.png

    Student应该占用20个字节,为啥最后是16个字节,这是因为内存对齐造成的, _no的4个字节占用了Person空出来的4个字节


    三、另外一种方式窥探

    Class 是一个指针
    现在我们来看第一个问题

    #import <objc/runtime.h>
    #import <malloc/malloc.h>
    
    int main(int argc, char * argv[]) {
        NSString * appDelegateClassName;
        @autoreleasepool {
            
            appDelegateClassName = NSStringFromClass([AppDelegate class]);
            
            NSObject *obj = [[NSObject alloc] init];
            NSLog(@"NSObject类实例对象的成员变量所占用的大小:8字节🍎%zd",class_getInstanceSize([NSObject class]));
            NSLog(@"obj指针所指向内存的大小:16字节🍎%zd",malloc_size((__bridge const void *)(obj)));
            
        }
        return UIApplicationMain(argc, argv, nil, appDelegateClassName);
    }
    
    
    image.png

    结果:


    image.png

    感觉红框中的其实就是 isa 指针
    现在可以回答开篇的第1个问题:

    一个指针变量所占用的大小(64bit环境下,8个字节,32bit环境下,4个字节)


    • 常用LLDB指令
      print 、p 打印
      po 打印对象
      memory read 读取内存地址
    Printing description of obj:
    <NSObject: 0x60000364c130>
    (lldb) p obj
    (NSObject *) $7 = 0x000060000364c130
    (lldb) po obj
    <NSObject: 0x60000364c130>
    
    (lldb) memory read 0x60000364c130
    0x60000364c130: 00 2d be 89 ff 7f 00 00 00 00 00 00 00 00 00 00  .-..............
    0x60000364c140: c8 fa a5 87 ff 7f 00 00 e4 85 22 6c 42 ae 26 a2  .........."lB.&.
    (lldb) 
    


    相关文章

      网友评论

          本文标题:iOS学习-OC对象的本质 01

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