在好多语言中字符串都是一个特殊的对象,在ObjC中也不例外。NSString作为一个对象类型存储在堆中,多数情况下它跟一般的对象类型没有区别,但是这里我们需求强调一点那就是字符串的引用计数器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #import <Foundation/Foundation.h>
int main(int argc,char *argv[]){ NSString *str1=@"Kenshin"; NSLog(@"retainCount(str1)=%i",(unsigned long)str1.retainCount); [str1 retain]; NSLog(@"retainCount(str1)=%i",(unsigned long)str1.retainCount); NSString *str2=[NSString stringWithString:@"Kaoru"]; NSLog(@"retainCount(str2)=%i",str2.retainCount); [str1 retain]; NSLog(@"retainCount(str2)=%i",str2.retainCount); NSString *str2_1=[NSString stringWithString:[NSString stringWithFormat:@"Kaoru %@",@"sun"]]; NSLog(@"retainCount(str2_1)=%i",str2_1.retainCount); [str2_1 release]; [str2_1 release]; NSString *str3=[NSString stringWithFormat:@"Rosa %@",@"Sun"]; NSLog(@"retainCount(str3)=%i",str3.retainCount); [str3 retain]; NSLog(@"retainCount(str3)=%i",str3.retainCount); [str3 release]; [str3 release]; NSString *str4=[NSString stringWithUTF8String:"Jack"]; NSLog(@"retainCount(str4)=%i",str4.retainCount); [str4 retain]; NSLog(@"retainCount(str4)=%i",str4.retainCount); [str4 release]; [str4 release]; NSString *str5=[NSString stringWithCString:"Tom" encoding:NSUTF8StringEncoding]; NSLog(@"retainCount(str5)=%i",str5.retainCount); [str5 retain]; NSLog(@"retainCount(str5)=%i",str5.retainCount); [str5 release]; [str5 release]; NSMutableString *str6=@"Jerry"; NSLog(@"retainCount(str6)=%i",str6.retainCount); [str6 retain]; NSLog(@"retainCount(str6)=%i",str6.retainCount); [str6 release]; [str6 release]; NSMutableArray *str7=[NSMutableString stringWithString:@"Lily"]; NSLog(@"retainCount(str7)=%i",str7.retainCount); [str7 retain]; NSLog(@"retainCount(str7)=%i",str7.retainCount); [str7 release]; [str7 release]; return 0; }
|
看完上面的例子如果不了解NSString的处理你也许会有点奇怪(注意上面的代码请在Xcode5下运行)?请看下面的解释
1.str1是一个字符串常量,它存储在常量区,系统不会对它进行引用计数,因此无论是初始化还是做retain操作其引用计数器均为-1;
2.str3、str4、str5创建的对象同一般对象类似,存储在堆中,系统会对其进行引用计数;
3.采用stringWithString定义的变量有些特殊,当后面的字符串是字符串常量,则它本身就作为字符串常用量存储(str2),类似于str1;如果后面的参数是通过类似于str3、str4、str5的定义,那么它本身就是一个普通对象,只是后面的对象引用计数器默认为1,当给它赋值时会做一次拷贝操作(浅拷贝),引用计数器加1,所有str2_1引用计数器为2;
4.str6其实和str1类似,虽然定义的是可变数组,但是它的本质还是字符串常量,事实上对于可变字符串只有为字符串常量时引用计数器才为-1,其他情况它的引用计数器跟一般对象完全一致;
Tips
注意上面这段代码的运行结果是在Xcode5中运行的结果,事实上针对最新的Xcode6由于LLVM的优化,只有str2_1和str7的引用计数器为1(str7 retain一次后第二次为2),其他均为-1。