关于NSString的retainCount的各种结果原因
转载:http://blog.csdn.net/onlyou930/article/details/6932529
http://www.cnblogs.com/celestial/archive/2012/10/10/2719169.html
1. 字符串常量
NSString *s = @"test";
NSLog(@"s:%d",[s retainCount]); // -1或2147483647(即UINT_MAX ( Maximum value an `unsigned int'))
因为"test"为字符串常量,系统不会收回,也不会对其作引用计数,即使我们对s如何retain或release。
2. stringWithFormat
NSString *s = [NSString stringWithFormat:@"%s", "test"];
NSLog(@"s:%d",[s retainCount]); // 1
使用stringWithFormat创建的NSString为变量,系统会进行引用计数。
2. stringWithString
stringWithString这个方法比较特别:它的retainCount取决于它后面跟的string对象
NSString *s1 = [NSString stringWithString:@"test"];
NSString *s2 = [NSString stringWithString:[NSString stringWithFormat:@"test,%d",1]];
NSLog(@"s1:%d",[s1 retainCount]); // 2147483647
NSLog(@"s2:%d",[s2 retainCount]); // 2
可以看到第一个为"常量"对象,其retainCount方法的实现返回的是maxIntValue。
第二个为2,这里也很好理解,也证明了前面说的,这个方法生成的只是一个对另一个对象的引用。一个对象实例,两次的stringWithString,它的retainCount为2,同时都被当前的AutoreleasePool管理。
NSString是一个不可变的字符串对象。这不是表示这个对象声明的变量的值不可变,而是表示它初始化以后,你不能改变该变量所分配的内存中的值,但你可以重新分配该变量所处的内存空间。
----------------我是华丽丽的分割线---------------
生成一个NSString类型的字符串有三种方法:
方法1.直接赋值: NSString *str1 = @"my string";
方法2.类函数初始化生成: NSString *str2 = [NSString stringWithString:@"my string"];
方法3.实例方法初始化生成: NSString *str3 = [[NSString alloc] initWithString:@"my string"];
NSString *str4 = [[NSString alloc]initWithFormat:@"my string"];
区别1: 方法一生成字符串时,不会初始化内存空间,所以使用结束后不会释放内存;
而其他三个都会初始化内存空间,使用结束后要释放内存;
在释放内存时方法2和3也不同,方法2是autorelease类型,内存由系统释放;方法3则必须手动释放
区别2:用Format初始化的字符串,需要初始化一段动态内存空间,如:0x6a42a40;
而用String声明的字符串,初始化的是常量内存区,如:0x46a8,常量内存区的地址,只要值相同,占用的地址空间是一致的。
所以str3和str1的地址一致,但是str4和str1的地址不一致。
------------华丽丽的分割线--------------------
生成一个NSString类型的字符串有三种方法:
方法1.直接赋值: NSString *testStr1 = @"a";
方法2.类函数初始化生成:
NSString *testStr2 = [NSString stringWithString:@"b"];
NSString *testStr3 = [NSString stringWithFormat:@"c"];
方法3.实例方法初始化生成:
NSString *testStr4 = [[NSString alloc] initWithString:@"d"];
NSString *testStr5 = [[NSString alloc] initWithFormat:@"e"];
首先查看它们的地址和引用计数:
2012-10-11 17:35:25.601 StringDemo[8514:11303] test1Address:0x4698
2012-10-11 17:35:25.601 StringDemo[8514:11303] test2Address:0x46a8
2012-10-11 17:35:25.602 StringDemo[8514:11303] test3Address:0x746c820
2012-10-11 17:35:25.602 StringDemo[8514:11303] test4Address:0x46c8
2012-10-11 17:35:25.603 StringDemo[8514:11303] test5Address:0x7455990
2012-10-11 17:35:25.585 StringDemo[8514:11303] test1:4294967295
2012-10-11 17:35:25.586 StringDemo[8514:11303] test2:4294967295
2012-10-11 17:35:25.596 StringDemo[8514:11303] test3:1
2012-10-11 17:35:25.600 StringDemo[8514:11303] test4:4294967295
2012-10-11 17:35:25.600 StringDemo[8514:11303] test5:1
从上可以看出,test1,test2,test4都是在一个内存区域,也就是上文所说的常量内存区。test3,test5在一个内存区,也就是堆区。
这里就有一个疑问:[NSString alloc] initWithString:@"d"这种方式初始化的字符串,也就是test4.应该是位于堆区的,但为什么会跑到常量内存区来呢?据说是因为xcode对这种方式做了处理,还包括[NSString stringWithString:@"b"]这种方式,这两种初始化字符串都等同于@"ddd"了。所以说test2,test4都同等于test1了。
还有,对于NSString *testStr3 = [NSString stringWithFormat:@"c"];这种初始化的字符串,只要一写release语句就会挂掉,但其它的都不会挂掉,test1,test2,test4好理解,因为release本来就不会起作用;但testStr5无论release多少次也不会挂掉,只会在控制台报警告:malloc: *** error for object 0x744d650: double free*** set a breakpoint in malloc_error_break to debug。这个猜测应该是也xcode做了优化吧。
对现在4.4之后的编译器,NSString *testStr2 = [NSString stringWithString:@"b"];这种写法会报警告了:Using 'stringWithString' with a literal is redundant。也就是说这种写法是多余的了,它给的建议是用=@"b"这种方式来代替了。
小结下吧:
对NSString的初始化方法,对于test1,test2,test4这三种的话建议用=@“字符串”来使用,因为本来就是一样的。test3,test5这两种的话,建议用texst3这种,方便点,不用管内存问题,系统自已管理。
整理了一下,这个就能说通
关于NSString的retainCount的各种结果原因的更多相关文章
- 反汇编分析NSString,你印象中的NSString是这样吗
我们先来定义三个NSString -(void) testNSString { NSString* a = @"abc"; NSString* b = [NSString stri ...
- Objective-C中的内存管理
在编程语言中是少不了对内存的管理的,内存对于计算机来说是宝贵的资源,所以对使用不到的资源进行回收是很有必要的.OC中使用引用计数和垃圾回收来管理内存,在OC中为每个对象分配一个引用计数器,当对象刚刚被 ...
- MRC
MRC 关于NSString,retainCount为-1 C方法中含有Copy的方法名, 都要释放 例如CFRealse(ref) 字符串常量,因为one为字符串常量,系统不会回收,也不会对其作引用 ...
- 使用SQLCipher加密数据库
Xcode中集成了免费的sqlite,但是不提供加密的模块,突然有一天,蛋疼的客户要求把数据进行加密,于是乎就寻找使用简单并且可以把数据迁移过度到加密数据库的框架. SQLCipher是第三方的开 ...
- iOSSingleton设计模式详细的说明教程
iOS有很多的设计模式,当然,不管是什么语言有很多的设计模式.辛格尔顿是一种之一,辛格尔顿,它从字面上是一个单独的实例,首先,它是只有一个单一的,其次,它是一个实例.我们知道,在iOS用于开发Obje ...
- ios 数组和字典
一.数组. 数组只能存放对象类型的数据 2.数组中的对象是有序的 (index) (一)可变数组 NSArray:NSObject 不可变数组 作用:容器类 存放的是对象类型的数据, ...
- NSString与奇怪的retainCount
话题从sunnyxx的<黑幕背后的Autorelease>开始 文章开头有个小例子 __weak id reference = nil;- (void)viewDidLoad { [sup ...
- IOS开发之关于NSString和NSMutableString的retainCount
1. 字符串常量 NSString *s = @"test"; NSLog(@"s:%lx",[s retainCount]); //fffffffffffff ...
- 10.OC中retainCount返回值不准的原因
翻看该方法的参考文档,苹果对retainCount方法的描述如下: retainCount Do not use this method. (required) - (NSUInteger)retai ...
随机推荐
- MYSQL注入天书之后记
后记 对于工具的看法: 我之所以在每个例子中只写了几个示例,是因为我希望你能通过这一两个示例举一反三将其他的列出来.如果让我来完成每一次完整的注入,应该在知道原理的情况下,必然使用工具或者自己写代码实 ...
- C#&java重学笔记(泛型)
C#部分: 1.泛型的出现主要用于解决类.接口.委托.方法的通用性,通过定义泛型类.接口.委托.方法,可以让不同类型的数据使用相同运算规则处理数据,方便了开发. 2.利用System.Nullable ...
- NSOJ 鬼泣
今天组队赛的一道最短路的题,给你一个矩阵,矩阵上有L,R,G,A,分别表示当你到达这个点的时候你要向左,向右,向前,向后走,如果要向别的方向走需要花费1点的魔力,正常情况下走需要花费1点的时间.问花费 ...
- ZOJ3550 Big Keng(三分)
题意:给定一个立体的图形,上面是圆柱,下面是圆台,圆柱的底面半径和圆台的上半径相等,然后体积的V时,问这个图形的表面积最小可以是多少.(不算上表面).一开始拿到题以为可以YY出一个结果,就认为它是圆锥 ...
- MJRefresh插件引起的错误
添加的头部或者尾部刷新,离开这个界面的时候需要移除 - (void)dealloc { [_tableView removeHeader];} 不同版本的处理的方式不同 报的错误: 类的一个实例 ...
- spring mvc绑定对象String转Date解决入参不能是Date的问题
使用spring的mvc,直接将页面参数绑定到对象中,对象中有属性为Date时会报错,此时需要处理下. 同样的,其他的需要处理的类型也可以用这种方法. 在controller中加入代码 @InitBi ...
- 利用PHP SOAP实现WEB SERVICE
php有两个扩展可以实现web service,一个是NuSoap,一个是php 官方的soap扩展,由于soap是官方的,所以我们这里以soap来实现web service.由于默认是没有打开soa ...
- Java集合框架(四)
Collections 集合框架的工具类 着重讲解以下方法: 1.sort(): 1º根据元素的自然顺序对指定列表按升序进行排序,列表中的所有元素都必须实现comparable接口. pu ...
- MongoDB (二) MongoDB 优点
任何关系型数据库,具有典型的架构设计,显示表和这些表之间的关系.虽然在 MongoDB中,没有什么关系的概念. MongoDB比RDBMS的优势 架构:MongoDB是文档型数据库,其中一个集合保存不 ...
- java web线程池
线程池 要知道在计算机中任何资源的创建,包括线程,都需要消耗系统资源的.在WEB服务中,对于web服 务器的响应速度必须要尽可能的快,这就容不得每次在用户提交请求按钮后,再创建线程提供服务 .为了减少 ...