Class中的isa指针本质

1.iOS存储优化

BOOL类型占1字节,如何将多个BOOL类型数据存储在一个字节中?可以用一字节的每一位表示一个BOOL类型

  1. 实现原理

#import "Person.h"
#define TallMask (1<<0) //表示1左移一位:0b 0000 0001
#define RichMask (1<<1) //表示1左移一位:0b 0000 0010
#define HandsomeMask (1<<2) //表示1左移一位:0b 0000 0100
@interface Person()
{
    char _savePersonInfo;
}
@end
@implementation MJPerson

-(instancetype)init{
    if (self = [super init]) {
        //用一个字节来存储三个变量:从最右往左依次为Tall、Rich、Handsome
        _savePersonInfo = 0b00000101;
    }
    return self;
}

/*思路
 0000 0000(_saveBox)
|0000 0001(掩码)
 ---------
 0000 0001(赋值tall为1)
 
 0000 0000
&1111 1110(掩码取反)
 ---------
 0000 0000(赋值tall为0)
 
 1.如果赋的值为1,则按位或;
 2.如果赋的值为0,则掩码先取反,后按位与
 */
-(void)setTall:(BOOL)tall{
    if (tall) {
        //直接或运算
        _savePersonInfo |=TallMask;
    }else{
        //掩码取反再与运算
        _savePersonInfo &= ~TallMask;
    }
}
-(void)setRich:(BOOL)rich{
    if (rich) {
        _savePersonInfo |= rich;
    }else{
        _savePersonInfo &= ~rich;
    }
}
-(void)setHandsome:(BOOL)handsome{
    if (handsome) {
        _savePersonInfo |= handsome;
    }else{
        _savePersonInfo &= ~handsome;
    }
}
/*思路
 0000 0101
&0000 0001
 ---------
 0000 0001(取出tall值)
 
 1.按位与,用掩码取出_saveBox中特定位;
 2.结果>=1,取反为0,再取反为1;同理,为0则双取反后为0;
 */
-(BOOL)tall{
    return !!(_savePersonInfo & TallMask);
}

-(BOOL)rich{
    return !!(_savePersonInfo & RichMask);
}

-(BOOL)handsome{
    return !!(_savePersonInfo & HandsomeMask);
}

@end

   2.代码优化,结构体支持位域,用结构体来替换实现

@interface Person()
{
    struct{
        char tall :1;//声明用一位来存储,并且从右至左来存,也可以char tall :3;来声明用3位存储
        char rich :1;
        char handsome :1;
    }_tallRichHandsome;
}


@end
@implementation Person

-(instancetype)init{
    if (self = [super init]) {
        //用一个字节来存储三个变量:从最右往左依次为Tall、Rich、Handsome
        _savePersonInfo = 0b00000101;
    }
    return self;
}


-(void)setTall:(BOOL)tall{
    _tallRichHandsome.tall = tall;
}
-(void)setRich:(BOOL)rich{
    _tallRichHandsome.rich = rich;
}
-(void)setHandsome:(BOOL)handsome{
    _tallRichHandsome.handsome = handsome;
}

-(BOOL)tall{
    return !!_tallRichHandsome.tall;//非0(包括负数)取反为0
}

-(BOOL)rich{
   return !!_tallRichHandsome.rich;//非0(包括负数)取反为0
}

-(BOOL)handsome{
    return !!_tallRichHandsome.handsome;//非0(包括负数)取反为0
}

3.代码优化,用共同体可以同时用以上两种方式来写

    union{
        char bits;
        
        //这个结构体只是一个摆设,增加可读性(但是也可以直接_tallRichHandsome.tall来使用)
        struct{
            char tall :1;//声明用一位来存储,并且从右至左来存
            char rich :1;
            char handsome :1;
        };
    }_tallRichHandsome;

总结:回归到实例对象的底层结构中,打印isa指针本来应该是类对象的地址,但是并不是,这事因为isa是一个共同体,需要进行位运算才能获取到真正的类对象地址。

union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }
    Class cls;
    uintptr_t bits;
#if SUPPORT_PACKED_ISA
 
    // extra_rc must be the MSB-most field (so it matches carry/overflow flags)
    // nonpointer must be the LSB (fixme or get rid of it)
    // shiftcls must occupy the same bits that a real class pointer would
    // bits + RC_ONE is equivalent to extra_rc + 1
    // RC_HALF is the high bit of extra_rc (i.e. half of its range)
    // future expansion:
    // uintptr_t fast_rr : 1;     // no r/r overrides
    // uintptr_t lock : 2;        // lock for atomic property, @synch
    // uintptr_t extraBytes : 1;  // allocated with extra bytes
# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
    struct {
        uintptr_t nonpointer        : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
        uintptr_t magic             : 6;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 19;
#       define RC_ONE   (1ULL<<45)
#       define RC_HALF  (1ULL<<18)
    };
# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
#   define ISA_MAGIC_MASK  0x001f800000000001ULL
#   define ISA_MAGIC_VALUE 0x001d800000000001ULL
    struct {
        uintptr_t nonpointer        : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
        uintptr_t magic             : 6;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 8;
#       define RC_ONE   (1ULL<<56)
#       define RC_HALF  (1ULL<<7)
    };
# else
#   error unknown architecture for packed isa
# endif
// SUPPORT_PACKED_ISA
#endif
 
 
#if SUPPORT_INDEXED_ISA
# if  __ARM_ARCH_7K__ >= 2
#   define ISA_INDEX_IS_NPI      1
#   define ISA_INDEX_MASK        0x0001FFFC
#   define ISA_INDEX_SHIFT       2
#   define ISA_INDEX_BITS        15
#   define ISA_INDEX_COUNT       (1 << ISA_INDEX_BITS)
#   define ISA_INDEX_MAGIC_MASK  0x001E0001
#   define ISA_INDEX_MAGIC_VALUE 0x001C0001
    struct {
        uintptr_t nonpointer        : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t indexcls          : 15;
        uintptr_t magic             : 4;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 7;
#       define RC_ONE   (1ULL<<25)
#       define RC_HALF  (1ULL<<6)
    };
# else
#   error unknown architecture for indexed isa
# endif
// SUPPORT_INDEXED_ISA
#endif
};

 shiftcls才是真正的类对象地址,同理类对象指向元类对象也是这样。

class_rw_t也是通过class_data_bits bits共同体经过位运算获取到的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++,类的函数指针是可以用来指向类成员函数的指针。需要注意的是,类成员函数指针与普通函数指针有一些不同之处。 首先,类成员函数指针的类型与类成员函数的类型相关联。假设我们有一个类`MyClass`和一个成员函数`void func(int)`,那么对应的成员函数指针类型就是`void (MyClass::*)(int)`。其,`MyClass`是类名,`*`表示指针,`void`是返回类型,`(int)`是参数列表。 下面是一个简单的示例,演示了如何定义和使用类成员函数指针: ```cpp #include <iostream> class MyClass { public: void func(int num) { std::cout << "Hello from func: " << num << std::endl; } }; int main() { MyClass obj; void (MyClass::*funcPtr)(int) = &MyClass::func; // 定义类成员函数指针 // 通过指针调用类成员函数 (obj.*funcPtr)(42); return 0; } ``` 在上面的示例,我们首先定义了一个类`MyClass`和一个成员函数`func`。然后,在主函数,我们创建了一个`MyClass`的对象`obj`,并定义了一个类成员函数指针`funcPtr`,将其初始化为指向`func`函数。最后,我们通过指针调用了类成员函数,并输出了结果。 需要注意的是,类成员函数指针在调用时需要使用对象指针或引用来访问类成员函数。在示例,我们使用`(obj.*funcPtr)(42)`来调用`func`函数,其`obj`是对象,`.*`是成员访问操作符,`funcPtr`是类成员函数指针。 希望以上信息对你有帮助!如果你有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值