转载: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的各种结果原因的更多相关文章

  1. 反汇编分析NSString,你印象中的NSString是这样吗

    我们先来定义三个NSString -(void) testNSString { NSString* a = @"abc"; NSString* b = [NSString stri ...

  2. Objective-C中的内存管理

    在编程语言中是少不了对内存的管理的,内存对于计算机来说是宝贵的资源,所以对使用不到的资源进行回收是很有必要的.OC中使用引用计数和垃圾回收来管理内存,在OC中为每个对象分配一个引用计数器,当对象刚刚被 ...

  3. MRC

    MRC 关于NSString,retainCount为-1 C方法中含有Copy的方法名, 都要释放 例如CFRealse(ref) 字符串常量,因为one为字符串常量,系统不会回收,也不会对其作引用 ...

  4. 使用SQLCipher加密数据库

      Xcode中集成了免费的sqlite,但是不提供加密的模块,突然有一天,蛋疼的客户要求把数据进行加密,于是乎就寻找使用简单并且可以把数据迁移过度到加密数据库的框架. SQLCipher是第三方的开 ...

  5. iOSSingleton设计模式详细的说明教程

    iOS有很多的设计模式,当然,不管是什么语言有很多的设计模式.辛格尔顿是一种之一,辛格尔顿,它从字面上是一个单独的实例,首先,它是只有一个单一的,其次,它是一个实例.我们知道,在iOS用于开发Obje ...

  6. ios 数组和字典

    一.数组.  数组只能存放对象类型的数据  2.数组中的对象是有序的 (index)     (一)可变数组   NSArray:NSObject  不可变数组 作用:容器类 存放的是对象类型的数据, ...

  7. NSString与奇怪的retainCount

    话题从sunnyxx的<黑幕背后的Autorelease>开始 文章开头有个小例子 __weak id reference = nil;- (void)viewDidLoad { [sup ...

  8. IOS开发之关于NSString和NSMutableString的retainCount

    1. 字符串常量 NSString *s = @"test"; NSLog(@"s:%lx",[s retainCount]); //fffffffffffff ...

  9. 10.OC中retainCount返回值不准的原因

    翻看该方法的参考文档,苹果对retainCount方法的描述如下: retainCount Do not use this method. (required) - (NSUInteger)retai ...

随机推荐

  1. C#索引器及示例

    public class IndexSeletor<T> where T:struct { private List<T> _listObj; public IndexSele ...

  2. JDK中常见的package

    SUN公司在JDK中为程序开发者提供了各种实用类,这些类按功能不同分别被放入了不同的包中,供开发者使用,下面简要介绍其中最常用的几个包:1. java.lang — 包含一些Java语言的核心类,如S ...

  3. ubuntu安装 scala

    1. 配置路径 sudo gedit /etc/profile 2.在文件后面加入 export PATH=/home/sendi/scala-/bin:$PATH 3.更新 source /etc/ ...

  4. FastReport报表

    http://www.fastreportcn.com/product/FASTREPORT_dotNET.html

  5. PHP获取http头信息和CI中获取HTTP头信息的方法

    CI中获取HTTP头信息的方法: $this->input->request_headers() 在不支持apache_request_headers()的非Apache环境非常有用.返回 ...

  6. 【pku2115-C Looooops】拓展欧几里得-不定方程

    http://poj.org/problem?id=2115 题解:一个变量从A开始加到B,每次加C并mod2^k,问加多少次.转化为不定方程:C*x+2^K*Y=B-A //poj2115 #inc ...

  7. skip list

    概述 Skip list是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的.并且是Redis.Leve ...

  8. 【总结】杂谈Java异常处理

    软件开发中一个古老的说法是:80%的工作使用20%的时间.80%是指检查和处理错误所付出的努力.在许多语言中,编写检查和处理错误的程序代码很乏味,并使应用程序代码变得冗长.原因之一就是它们的错误处理方 ...

  9. ace-min.css

    textarea,input[type="text"],input[type="password"],input[type="datetime&quo ...

  10. JQuery获取浏览器窗口的高度和宽度

    <script type="text/javascript"> $(document).ready(function() { alert($(window).heigh ...