转载: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. POJ 2752 Seek the Name, Seek the Fame (KMP的next函数,求前缀和后缀的匹配长度)

    给一个字符串S,求出所有前缀,使得这个前缀也正好是S的后缀.升序输出所有情况前缀的长度.KMP中的next[i]的意义就是:前面长度为i的子串的前缀和后缀的最大匹配长度.明白了next[i],那么这道 ...

  2. SQL技术内幕-6 rank()over(order by XX COLLATE) 的用法

    DECLARE @Names TABLE ( name VARCHAR(20) ); INSERT INTO @Names VALUES ('DeSzmetch'),('DESZMETCH'),('D ...

  3. 简明Vim练级攻略(转)

    前言今天看到这篇文章,共鸣点非常多.它把Vim使用分为4个级别,目前我自己是熟练运用前面三级的命令,在培养习惯使用第四级.完全就是我这一年来坚持使用Vim的过程.所以不管怎么我要转载这篇文章.翻译自& ...

  4. ExtJs布局之Card

    <!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...

  5. android自动化环境搭建

    android自动化环境安装指南 1.appium相关安装(eclipse下)见http://www.cnblogs.com/wangcp-2014/p/5717589.html参考selenium的 ...

  6. 绑定CPU

    处理器的亲和性 软亲和性(affinity) 意味着进程并不会在处理器之间频繁迁移,而 硬亲和性(affinity) 则意味着进程需要在您指定的处理器上运行. 通常 Linux 内核都可以很好地对进程 ...

  7. 如何使用SPY++查找

    自动化测试中,如果需要做UI automation的时候往往需要抓取object的工具.实际上这种工具有很多,认识的大牛使用SPY++,于是我也选择了这个.下面列出基本使用方法.有点像XACC spy ...

  8. java应用程序利用Exe4j打包exe文件

    1.      使用简介: 把java应用程序打成exe文件我们可以借助第三方软件exe4j来完成.Exe4j大家可以在网上下载,下载地址是: http://www.ej-technologies.c ...

  9. ios开发中超简单抽屉效果(MMDrawerController)的实现

    ios开发中,展示类应用通常要用到抽屉效果,由于项目需要,本人找到一个demo,缩减掉一些不常用的功能,整理出一个较短的实例. 首先需要给工程添加第三方类库 MMDrawerController: 这 ...

  10. iOS开发--项目内存优化

    在用非ARC模式编写iOS程序的时候,造成程序内存泄露在所难免,后期我们一般会进行内存优化.自己比较常用的内存优化方法有两种 1.Analyze,静态分析内存泄露的方法.很简单,在Xcode菜单栏中点 ...