美文网首页
对象与isa

对象与isa

作者: miaohy | 来源:发表于2020-09-11 19:03 被阅读0次

    对象本质是什么?(结构体)怎么证明呢?
    首先了解一下clang,Clang是⼀个由Apple主导编写,基于LLVM的C/C++/Objective-C编译器
    终端执行如下命令

    clang -rewrite-objc LGPerson.m -o LGPerson.cpp
    

    打开LGPerson.cpp,可以看到LGPerson被编译成了一个结构体,其中有isa指针

    struct LGPerson_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
    };
    
    struct NSObject_IMPL {
        Class isa;
    };
    

    了解了对象的本质是结构体,那么结构体能被继承吗?通过在xcode中实际敲代码发现报错所以是不能被继承的。
    但我们可以通过另外一种方式也就是伪继承的方式实现,如下coding

    struct SuperPerson{
        int a;
    };
    
    struct SonPerson{ //大小等于a 4个字节 + b 4个字节 == 8个字节
        struct SuperPerson ll;
        int b;
    };
    

    那么如何调用呢?

     struct SuperPerson pp1;
      pp1.a = 10;
     struct SonPerson pp;
      pp.ll.a = 5;
    

    如上所示我们成功的通过SonPerson访问了SuperPerson的成员

    看到了结构体,再多吧啦点,结构体大小是怎样的呢?在内存是什么样子的呢?

    NSLog(@"%lu %lu",sizeof(pp1), sizeof(pp));
    2020-09-11 15:54:04.309319+0800 KCObjc[21290:479786] 4 8
    

    isa指针会用到联合体,那么什么是联合体,与结构体区别是啥呢?

    结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。
    coding例子如下

    union Person{
        char eye;
        struct{
            char eye_colr;
            BOOL show_eye;
        };
    };
    

    调用如下

     union Person person;
     person.eye = 's';
     person.eye_colr = 's';
     person.show_eye = false;
      NSLog(@"%lu",sizeof(person));
    2020-09-11 16:46:48.744520+0800 KCObjc[22164:509122] 2
    

    接下来看看对象成员isa相关
    通过objc源码分析可以看到isa初始化过程
    [LGPerson alloc]
    objc_alloc_init
    callAlloc
    ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
    alloc
    _objc_rootAlloc
    callAlloc
    _objc_rootAllocWithZone
    _class_createInstanceFromZone
    initInstanceIsa
    initIsa
    ASSERT(!isTaggedPointer());
    isa_t

    newisa.bits = ISA_MAGIC_VALUE;
    newisa.has_cxx_dtor = hasCxxDtor;
    newisa.shiftcls = (uintptr_t)cls >> 3; //uintptr是什么?主要用于指针的按位操作,因为不能对指针执行按位操作,为了对指针执行按位操作,需要将指针转换为unitpr类型
     isa = newisa;
    
    p newisa
    (isa_t) $7 = {
      cls = LGPerson
      bits = 8303516107940229
       = {
        nonpointer = 1
        has_assoc = 0
        has_cxx_dtor = 1
        shiftcls = 536871984
        magic = 59
        weakly_referenced = 0
        deallocating = 0
        has_sidetable_rc = 0
        extra_rc = 0
      }
    }
    

    isa初始化完毕,再验证

    po obj
    <LGPerson: 0x10190d0c0>
     x/4gx 0x10190d0c0
    0x10190d0c0: 0x001d800100002185 0x0000000000000000
    0x10190d0d0: 0x0000000080080000 0x000000010190d371
    
    po 0x001d800100002185 &0x0000000ffffffff8ULL
    LGPerson
    po 0x001d800100002185
    8303516107940229
    po 8303516107940229 & 0x0000000ffffffff8ULL
    LGPerson
    

    isa获取流程
    object_getClass
    getIsa
    ISA()
    (Class)(isa.bits & ISA_MASK)

    p (Class)(isa.bits & 0x00007ffffffffff8ULL)
    (Class) $3 = LGPerson
    

    相关文章

      网友评论

          本文标题:对象与isa

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