首先看下面这段代码
打印结果为: -1 1
我们忽略掉那个[str retain], 因为retain操作只会增加引用计数(相信系统, 相信Xcode). 那么为什么会是这样的打印结果?
首先需要明白的是, 引用计数机制只使用在堆中, 那么所有不保存在堆中的数据的引用计数都为-1.
在OC中, 几乎所有不可变对象(常量)都存在常量区(没有一一测试测, 有兴趣的可以试试), 内存管理由系统来做. 代码中的str系统默认是一个常量, 所以保存在常量区, 所以引用计数为-1. 哪怕是显式使用了alloc也同样不会保存在堆上, 所以引用计数还是-1.
但是, 既然常量保存在常量区, 那str1为什么引用计数为1?
这个, 私心想着(猜测), 所有可以有多个参数的初始化方法都有可能出现这种情况, 如果一个方法有多个参数, 那么方法内部就会有一个长度可变的数组保存参数(查看OC某些多参方法的声明, 出现va_list类型, 即可变数组类型), 因为长度不确定只能保存在堆中, 然后在方法执行过程中对数据处理后, 并没有将数据转存到栈中, 所以引用计数会+1;
亲测, 当format后面的字符串长度大于等于12时, 引用计数为1. 这个现象存在于initWithFormat:和stringWithFormat:方法, 至于有没有其他方法也会有这种情况不敢确定.
而在数组的初始化方法中initWithObjects:方法当参数为nil时引用计数为-1, 但是当有非nil参数的时候, 哪怕是空字符串@"", 引用计数都会成为1.
至于为什么会出现当参数长度大于某个值时才出现引用计数加一的情况, 可能是和栈内存分配有关, 因为不了解这个方面的细节, 就不多说了.