Runtime源码中的DisguisedPtr

2022-02-11  本文已影响0人  helinyu

头文件: objc-private.h

DisguisedPtr : 指针伪装、指针封装、掩饰指针

DisguisedPtr<T> 通过运算使指针隐藏于系统工具(如 leaks 工具),同时保持指针的能力,其作用是通过计算把保存的 T 的指针隐藏起来,实现指针到整数的映射。

template <typename T>
class DisguisedPtr {
    // typedef unsigned long uintptr_t;
    // 无符号 long 类型的 value 成员变量
    uintptr_t value;

    static uintptr_t disguise(T* ptr) { // 指针隐藏
        // 相当于直接把 T 指针的地址转化为 unsigned long 并取负值
        return -(uintptr_t)ptr;
    }

    static T* undisguise(uintptr_t val) { // 指针显示
        // 把 val 转为指针地址,对应上面的 disguise 函数
        return (T*)-val;
    }

 public:
    DisguisedPtr() { } // 构造函数

    // 初始化列表,显式初始化 value 成员变量
    DisguisedPtr(T* ptr) : value(disguise(ptr)) { } // 指针隐藏
    DisguisedPtr(const DisguisedPtr<T>& ptr) : value(ptr.value) { }

    // T* 赋值函数
    DisguisedPtr<T>& operator = (T* rhs) {
        value = disguise(rhs);
        return *this;
    }

    // 引用赋值函数
    DisguisedPtr<T>& operator = (const DisguisedPtr<T>& rhs) {
        value = rhs.value;
        return *this;
    }

    // 重载运算符
    operator T* () const {
        // 转为指针
        return undisguise(value);
    }
    T* operator -> () const { 
        // 转为指针
        return undisguise(value);
    }
    T& operator * () const { 
        // 转化为指针并取出该指针指向的内容
        return *undisguise(value);
    }
    T& operator [] (size_t i) const {
        return undisguise(value)[i];
    }
};

// fixme type id is weird and not identical to objc_object*
static inline bool operator == (DisguisedPtr<objc_object> lhs, id rhs) {
    return lhs == (objc_object *)rhs;
}
static inline bool operator != (DisguisedPtr<objc_object> lhs, id rhs) {
    return lhs != (objc_object *)rhs;
}

PS: 为什么要处理处理这个将值转化为负数?

地址 —— long —— 地址 : 起到了保护的作用。

只需要知道DisguisedPtr<T>功能上等价于T*即可

上一篇 下一篇

猜你喜欢

热点阅读