美文网首页
OC对象的本质

OC对象的本质

作者: sajiner | 来源:发表于2018-03-08 17:44 被阅读266次

    Objective-C的本质是什么

    学过编程的都知道,程序的编译原理即是由高级语言到机器语言的过程。Objective-C属于一种面向对象的高级语言,其编译过程如下:


    屏幕快照 2018-03-08 下午4.42.44.png

    即:Objective-C的面向对象都是基于C/C++的数据结构实现的,而Objective-C的对象、类主要是基于C/C++的结构体实现的,本质上Objective-C的对象、类就是结构体

    为什么OC对象的本质是结构体

    NSObject

    • 首先我们先创建一个程序


      屏幕快照 2018-03-08 下午4.49.03.png
    • 在main.m文件中创建一个NSObject的对象
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSObject *obj = [[NSObject alloc] init];
        }
        return 0;
    }
    
    • 使用终端将main.m编译成.cpp文件,命令如下:
      xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
      *打开main.cpp文件,搜索NSObject,可找到如下代码:
    istruct NSObject_IMPL {
        Class isa;
    };
    

    即:创建的obj就是一个结构体

    自定义的类

    在main.m文件中创建一个NSObject的对象

    @interface Student: NSObject {
        @public
        int _age;
        int _score;
    }
    @end
    
    @implementation Student
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Student *stu = [[Student alloc] init];
            stu->_age = 4;
            stu->_score=80;
        }
        return 0;
    }
    
    • 同上的方式生成main.cpp文件,搜索Student,可看到如下内容:
    struct Student_IMPL {
        struct NSObject_IMPL NSObject_IVARS; /// 相当于 Class isa;
        int _age;
        int _score;
    };
    /// 由上得到,即一个初创的Student对象所占的内存大小为:isa的大小
     + int的大小*2
    struct Student_IMPL {
        Class isa;
        int _age;
        int _score;
    };
    
    • 假设Student对象是一个结构体的话
    /// 定义这样的结构体
    struct Student_IMPL {
        Class isa;
        int _age;
        int _score;
    };
    
    @interface Student: NSObject {
        @public
        int _age;
        int _score;
    }
    @end
    
    @implementation Student
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Student *stu = [[Student alloc] init];
            stu->_age = 4;
            stu->_score=80;
           
            struct Student_IMPL *stu2 = (__bridge struct Student_IMPL *)stu;
            /// 如果打印结果是 4 - 80 的话,即可证明student对象本质上就是一个结构体
            NSLog(@"%d - %d", stu2->_age, stu2->_score);
        }
        return 0;
    }
    

    由打印结果反推得出:student对象本质上就是一个结构体

    扩展:NSObject所占内存大小是多少?

    因为OC对象的本质是结构体,那NSObject所占的内存大小就是结构体指针所占的大小。
    其实不然,准确的说法是:(以64bit为例)
    1、从内存中动态分配的大小是由malloc_size()函数获取的,即16
    2、NSObject对象真正使用的大小是 8 (可以通过运行时中的class_getInstanceSize:方法直接获取NSObject的内存大小)


    20180927补充
    malloc_size()为类对象动态分配的内存大小,是补齐之后的大小,即如果一个类对象需要的内存大小为81,通过malloc_size()方法获取的大小为96,即16的倍数;
    class_getInstanceSize()方法获取的内存大小也是补齐之后的大小,补齐规则按照类的成员变量所占内存最大值的整数倍

    相关文章

      网友评论

          本文标题:OC对象的本质

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