美文网首页
iOS中的结构体以及isa指针

iOS中的结构体以及isa指针

作者: 恋空K | 来源:发表于2019-07-20 16:59 被阅读0次

    struct 结构体名{

            类型名 成员名1;

            类型名 成员名2;

            ... ...

            类型名 成员名n;

    };

    struct {

    intage 

    ;inttag ;

    } structTwo;

    typedef可以对数据类型进行重命名,因此在定义结构体的时候可以使用它来简化操作。

    /**

    *  定义结构体

    */typedef struct {

        char*name;//姓名

    unsignedintage;//年龄

    } Student;

    int main(intargc,constchar* argv[]) {

        //声明结构变量Student student1 = {"jredu",21};

        return0;

    }

    //struct programmer proTest = {"Garvey",28,"13823992034"};

    ios-结构体和类的区别:

    1、结构体只能封装属性,类却不仅可以封装属性也可以封装方法。如果一个封装的数据有属性也有行为,就只能用类了。

    2、结构体变量分配在栈,而OC对象分配在堆,栈的空间相对于堆来说是比较小的,但是存储在栈中的数据访问效率相对于堆而言是比较高

    3、堆的存储空间比较大,存储在堆中的数据访问效率相对于栈而言是比较低的

    4、如果定义一个结构体,这个结构体中有很多属性,那么这个时候结构体变量在栈中会占据很多空间,这样的话就会降低效率

    5、我们使用结构体的时候最好是属性比较少的结构体对象如果属性较多的话就要使用类了

    6、结构体赋值的话是直接赋值,对象的指针,赋值的是对象的地址。

    思考: 一个OC对象在内存中是如何布局的。 NSObjcet的底层实现,点击NSObjcet进入发现NSObject的内部实现

    @interface NSObject {#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wobjc-interface-ivars

    "Class isa OBJC_ISA_AVAILABILITY;

    #pragma clang diagnostic pop}

    @end

    转化为c语言其实就是一个结构体

    struct NSObject_IMPL {

        Class isa;

    };

    那么这个结构体占多大的内存空间呢,我们发现这个结构体只有一个成员,isa指针,而指针在64位架构中占8个字节。也就是说一个NSObjec对象所占用的内存是8个字节。到这里我们已经可以基本解答第一个问题。但是我们发现NSObject对象中还有很多方法,那这些方法不占用内存空间吗?其实类的方法等也占用内存空间,但是这些方法所占用的存储空间并不在NSObject对象中。

    为了探寻OC对象在内存中如何体现,我们来看下面一段代码

    NSObject *objc = [[NSObject alloc] init];

    上面一段代码在内存中如何体现的呢?上述一段代码中系统为NSObject对象分配8个字节的内存空间,用来存放一个成员isa指针。那么isa指针这个变量的地址就是结构体的地址,也就是NSObjcet对象的地址。

    假设isa的地址为0x100400110,那么上述代码分配存储空间给NSObject对象,然后将存储空间的地址赋值给objc指针。objc存储的就是isa的地址。objc指向内存中NSObject对象地址,即指向内存中的结构体,也就是isa的位置。

    因此此结构体占用多少存储空间,对象就占用多少存储空间。因此结构体占用的存储空间为,isa指针8个字节空间+int类型_no4个字节空间+int类型_age4个字节空间共16个字节空间

    Student *stu = [[Student alloc] init];

    stu -> _no = 4;

    stu -> _age = 5;

    那么上述代码实际上在内存中的体现为,创建Student对象首先会分配16个字节,存储3个东西,isa指针8个字节,4个字节的_no ,4个字节的_age

    那么一个NSObject对象占用多少内存? NSObjcet实际上是只有一个名为isa的指针的结构体,因此占用一个指针变量所占用的内存空间大小,如果64bit占用8个字节,如果32bit占用4个字节。

    我们发现只要是继承自NSObject的对象,那么底层结构体内一定有一个isa指针。

    面试题:OC的类信息存放在哪里。 面试题:对象的isa指针指向哪里。

    OC的类信息存放在哪里 OC对象主要可以分为三种

    instance对象(实例对象)

    class对象(类对象)

    meta-class对象(元类对象)

    instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象

    NSObjcet *object1 = [[NSObjcet alloc] init];

    NSObjcet *object2 = [[NSObjcet alloc] init];

    object1和object2都是NSObject的instace对象(实例对象),但他们是不同的两个对象,并且分别占据着两块不同的内存。 instance对象在内存中存储的信息包括

    isa指针

    其他成员变量

    衍生问题:在上图实例对象中根本没有看到方法,那么实例对象的方法的代码放在什么地方呢?那么类的方法的信息,协议的信息,属性的信息都存放在什么地方呢?

    每一个类在内存中有且只有一个class对象。可以通过打印内存地址证明

    class对象在内存中存储的信息主要包括

    isa指针

    superclass指针

    类的属性信息(@property),类的成员变量信息(ivar)

    类的对象方法信息(instance method),类的协议信息(protocol)

    成员变量的值时存储在实例对象中的,因为只有当我们创建实例对象的时候才为成员变赋值。但是成员变量叫什么名字,是什么类型,只需要有一份就可以了。所以存储在class对象中。

    类方法放在那里? 元类对象 meta-class

    每个类在内存中有且只有一个meta-class对象。 meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括

    isa指针

    superclass指针

    类的类方法的信息(class method)

    meta-class对象和class对象的内存结构是一样的,所以meta-class中也有类的属性信息,类的对象方法信息等成员变量,但是其中的值可能是空的。

    对象的isa指针指向哪里

    当对象调用实例方法的时候,我们上面讲到,实例方法信息是存储在class类对象中的,那么要想找到实例方法,就必须找到class类对象,那么此时isa的作用就来了。

    [stu studentMethod];

    instance的isa指向class,当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用。

    当类对象调用类方法的时候,同上,类方法是存储在meta-class元类对象中的。那么要找到类方法,就需要找到meta-class元类对象,而class类对象的isa指针就指向元类对象

    [Student studentClassMethod];复制代码

    class的isa指向meta-class 当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

    当对象调用其父类对象方法的时候,又是怎么找到父类对象方法的呢?,此时就需要使用到class类对象superclass指针。

    [stu personMethod];

    [stu init];

    当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用,同样如果Person发现自己没有响应的对象方法,又会通过Person的superclass指针找到NSObject的class对象,去寻找响应的方法

    当类对象调用父类的类方法时,就需要先通过isa指针找到meta-class,然后通过superclass去寻找响应的方法

    [Student personClassMethod];[Student load];复制代码

    当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

    https://juejin.im/post/5ac81c75518825556534c0af

    对isa、superclass总结

    instance的isa指向class

    class的isa指向meta-class

    meta-class的isa指向基类的meta-class,基类的isa指向自己

    class的superclass指向父类的class,如果没有父类,superclass指针为nil

    meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class

    instance调用对象方法的轨迹,isa找到class,方法不存在,就通过superclass找父类

    class调用类方法的轨迹,isa找meta-class,方法不存在,就通过superclass找父类

    本文面试题总结:

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

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

    对象的isa指针指向哪里?

    答:instance对象的isa指针指向class对象,class对象的isa指针指向meta-class对象,meta-class对象的isa指针指向基类的meta-class对象,基类自己的isa指针也指向自己。

    OC的类信息存放在哪里?

    答:成员变量的具体值存放在instance对象。对象方法,协议,属性,成员变量信息存放在class对象。类方法信息存放在meta-class对象。

    相关文章

      网友评论

          本文标题:iOS中的结构体以及isa指针

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