Weak的实现-&SideTables()[oldObj]
&SideTables()[oldObj]
这是什么?很多人看到这里都被这操作搞蒙了,下面分三步来理解,分别是SideTables()
、[oldObj]
、&
。先贴上入口的代码
id oldObj;
SideTable *oldTable;
oldObj = *location;
oldTable = &SideTables()[oldObj];
1. 理解SideTables()
首先SideTables()
是一个静态函数,完全体是这样的
static StripedMap<SideTable>& SideTables() {
return SideTablesMap.get();
}
函数体里面调用了一个全局的静态变量SideTablesMap
的get()
方法,
静态变量里面保存了所有的SideTable
。的声明如下:
static objc::ExplicitInit<StripedMap<SideTable>> SideTablesMap;
可以看出SideTablesMap
是在命名空间objc下面的一个ExplicitInit
类,它里面实现了get()
方法,如下
Type &get() {
return *reinterpret_cast<Type *>(_storage);
}
对于不熟悉c++的理解下面这几点基本就能看懂:
- c++ 中的引用
&
,在c++中&
除了有取地址
的作用还可以作为引用
。方法返回的是一个引用,如果没有c++基础的很容易误认为返回了一个指针。 - c++中的模板
template
,泛型Type
是通过模板传入的,即StripedMap
。 从上面声明SideTablesMap
的地方可以看到,这里是个模板的嵌套,StripedMap
是ExplicitInit
模板的泛型;SideTable
是StripedMap
模板的泛型。 - c++中的
reinterpret_cast<new_type>(expression)
,它可以将两种任何类型进行转换,新值和旧值(expression)有相同的比特位。
最后用*
取转换后得到的地址的所保存的值,返回,所以说这里返回的不是指针。
Type *
就相当于StripedMap *
,所以get()
方法返回的就是StripedMap
结构体实例。
2. 理解[oldObj]
这里的[]
其实是对[]
进行了重载
T& operator[] (const void *p) {
return array[indexForPointer(p)].value;
}
在indexForPointer()
方法里,先将结构体指针oldObj
转化成和其有相同比特位的地址,再进行位移、异或、去模操作得到一个从0-63位之间的index
,通过index
,拿到数组里面的PaddedT
结构体,返回该结构体的value
成员即结构体SideTable
。
static unsigned int indexForPointer(const void *p) {
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
return ((addr >> 4) ^ (addr >> 9)) % StripeCount;
}
struct PaddedT {
T value alignas(CacheLineSize);
};
其实StripedMap
是一个以void *p
为key
,PaddedT
为value
的的表。
3. &
最后对SideTables()[oldObj]
即SideTable
取地址,这样就和SideTable *newTable;
对上了。