引言
大家都知道,Objective-C 有 4 个对象所有权修饰符(Ownership Qualifier),分别是:
__strong
__weak
__unsafe_unretained
__autoreleasing
在日常开发中日常用的最多的就是 __weak
,几乎都是为了解决循环引用的问题。__strong
是一个变量默认的修饰符,不需要写。__unsafe_unretained
因为它的不安全,基本上不会去使用它。__autoreleasing
见得最多的地方估计就是 NSError * __autoreleasing *
这个类型声明了,似乎也没有地方需要自己写。
看到 NSError * __autoreleasing *
这个类型,不禁会思考,这个 __autoreleasing
为啥放在两个星号中间呢,如果放在两个星号的左边,或者放在两个星号的右边行不行呢?
于是又开始思考另一个相关的问题。我们知道声明常量的时候,const 的位置不同,实际含义就会不同。比如:
NSObject const *object;
这里 object 是一个指针,指向一个 NSObject 类型的常量(通常把这种指针叫做指向常量的指针,或者常量指针)
这样声明的结果是 object 本身可以修改,但是 object 指向的内容不能修改。
NSObject * const object;
这里的 object 是一个常量,它的类型是一个指针(通常把这种类型叫做指针常量)
这样声明的结果是 object 本身不可以修改,但是 object 指向的内容可以修改。
但是因为 Objective-C 不支持对对象指针的解引用进行赋值,因此 object 指向的内容也无法修改。即 *str1 = *str2;
这类操作是不允许的。
const NSString *str = @"this is a string";
上面代码中的 const 其实是毫无意义的。
还有 object 本身和 object 指向的内容都不能修改的情况,即:
NSObject const * const object;
那么作为类比,对于 __strong 修饰符来说:
NSObject * __strong o;
NSObject __strong * o;
上面两句代码有什么区别?第二行中的 * 和 o 之间,日常开发时是不写空格的,这里只是为了对齐。
NSObject * __strong o;
和 NSObject __strong *o;
的区别
探索步骤1,转成 C++ 代码
int main(int argc, const char * argv[]) {
NSObject * __strong o1;
NSObject __strong *o2;
return 0;
}
将上面这个 main 函数转成 C++ 代码后的结果为:
int main(int argc, const char * argv[]) {
NSObject __attribute__((objc_ownership(strong))) *o1;
NSObject * __attribute__((objc_ownership(strong))) o2;
return 0;
}
看上去 __strong
被类似宏替换的操作替换成了 __attribute__((objc_ownership(strong)))
,看不出什么东西。
探索步骤2,查看汇编代码
int main(int argc