NSString:
 //main.m
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) {
@autoreleasepool { NSString *str1 = @"aaa";
NSString *str2 ;
NSString *str3 ;
NSString *str4 ;
NSString *str5 ;
NSString *str6 ; str2 = [NSString stringWithString:str1];
str3 = str1;
str4 = [[NSString alloc]initWithString:str1];
str5 = [str1 copy];
str6 = [str1 mutableCopy]; NSLog(@"@\"aaa\" address = %p", @"aaa"); // 输出字符串aaa的地址。
NSLog(@"change before:");
NSLog(@" str1 = %@", str1); // 输出字符串str1的内容
NSLog(@" str1 address = %p", str1); // 输出字符串str1的内容所在地址。
NSLog(@" str2 = %@", str2); // 输出字符串str2的内容
NSLog(@" str2 address = %p", str2); // 输出字符串str2的内容所在地址。
NSLog(@" str3 = %@", str3); // 输出字符串str3的内容
NSLog(@" str3 address = %p", str3); // 输出字符串str3的内容所在地址。
NSLog(@" str4 = %@", str4); // 输出字符串str4的内容
NSLog(@" str4 address = %p", str4); // 输出字符串str4的内容所在地址。
NSLog(@" str5 = %@", str5); // 输出字符串str5的内容
NSLog(@" str5 address = %p", str5); // 输出字符串str5的内容所在地址。
NSLog(@" str6 = %@", str6); // 输出字符串str6的内容
NSLog(@" str6 address = %p", str6); // 输出字符串str6的内容所在地址。 NSLog(@" ");
NSLog(@"@\"bbb\" address = %p", @"bbb"); NSLog(@"change after:");
str1 = @"bbb";
NSLog(@" str1 = %@", str1); //输出修改后str1的内容
NSLog(@" str1 address = %p", str1); //输出修改后str1的内容所在地址
NSLog(@" str2 = %@", str2); //输出修改后str2的内容
NSLog(@" str2 address = %p", str2); //输出修改后str2的内容所在地址
NSLog(@" str3 = %@", str3); //输出修改后str3的内容
NSLog(@" str3 address = %p", str3); //输出修改后str3的内容所在地址
NSLog(@" str4 = %@", str4); //输出修改后str4的内容
NSLog(@" str4 address = %p", str4); //输出修改后str4的内容所在地址
NSLog(@" str5 = %@", str5); //输出修改后str5的内容
NSLog(@" str5 address = %p", str5); //输出修改后str5的内容所在地址
NSLog(@" str6 = %@", str6); //输出修改后str6的内容
NSLog(@" str6 address = %p", str6); //输出修改后str6的内容所在地址 NSLog(@" @\"aaa\" address = %p", @"aaa"); //再次输出修改后字符串aaa的地址
 运行结果:

 1 -- ::49.451 copyTest[:] @"aaa" address = 0x100001050
-- ::49.452 copyTest[:] change before:
-- ::49.452 copyTest[:] str1 = aaa
-- ::49.452 copyTest[:] str1 address = 0x100001050
-- ::49.453 copyTest[:] str2 = aaa
-- ::49.453 copyTest[:] str2 address = 0x100001050
-- ::49.453 copyTest[:] str3 = aaa
-- ::49.453 copyTest[:] str3 address = 0x100001050
-- ::49.453 copyTest[:] str4 = aaa
-- ::49.453 copyTest[:] str4 address = 0x100001050
-- ::49.453 copyTest[:] str5 = aaa
-- ::49.453 copyTest[:] str5 address = 0x100001050
-- ::49.453 copyTest[:] str6 = aaa
-- ::49.453 copyTest[:] str6 address = 0x100203930
-- ::49.453 copyTest[:]
-- ::49.453 copyTest[:] @"bbb" address = 0x100001270
-- ::49.453 copyTest[:] change after:
-- ::49.453 copyTest[:] str1 = bbb
-- ::49.453 copyTest[:] str1 address = 0x100001270
-- ::49.453 copyTest[:] str2 = aaa
-- ::49.453 copyTest[:] str2 address = 0x100001050
-- ::49.454 copyTest[:] str3 = aaa
-- ::49.454 copyTest[:] str3 address = 0x100001050
-- ::49.454 copyTest[:] str4 = aaa
-- ::49.454 copyTest[:] str4 address = 0x100001050
-- ::49.454 copyTest[:] str5 = aaa
-- ::49.454 copyTest[:] str5 address = 0x100001050
-- ::49.454 copyTest[:] str6 = aaa
-- ::49.454 copyTest[:] str6 address = 0x100203930
-- ::49.454 copyTest[:] @"aaa" address = 0x100001050
Program ended with exit code:

结果分析:

(1)在定义str1时就先把字符串@"aaa"赋值给str1,输出时 @"aaa"和str1的地址相同,都是 0x100001050 。

(2)接着以三种不同的方式将str1赋值给str2, str3, str4

(3)再次给str1赋值,这次将字符串@"bbb"赋值给str1。 不同的是,我们在赋值前先输出一次字符串@"bbb"的地址,根据输出结果发现又与str1的地址相同,但地址已经发生变化 0x100001050 --> 0x100001270 。由此可以发现,不可变字符串NSString在第一次赋值时,指向一个内存空间,当它被再次被赋值于不同的字符串时,它会指向另一个内存空间,这与可变字符串NSMutableString不同(稍后会对NSMutableString进行测试)。

不可变字符串NSString的“不可变”我理解为是它引用的地址的那个内容不能改变,但是它引用的地址是可以改变的,有点拗口:

我把aaa赋值给str1,没有改变aaa这个字符串,当然也没有改变str1。当我再次赋值bbb给str1时,似乎是str1引用的地址-0x100001050 的内容(即aaa)改变成了bbb,其实不然。事实上我们是改变了str1引用的地址来实现这种“假象”的。str1的引用地址已经由 0x100001050(含有字符串aaa的地址)变为 0x100001270(含有字符串bbb的地址)。我们通过最后一行输出结果:字符串aaa的地址仍是 0x100001050,就可以知道在str1被bbb重新赋值的这个过程中aaa没有发生任何改变。

(4)str2,str3,str4的结果就很清晰了。他们都只是引用了aaa赋值给str1时的地址。所以他们都引用这个地址0x100001050,这个地址里面的内容也就是aaa了。

(5)str5,str6分别是str1使用copy和MutableCopy方法创建的副本。 根据输出可以看到在str1改变前,通过copy创建的副本str5引用的地址,与str1引用的地址相同-0x100001050;MutableCopy创建的副本引用的地址(0x100203930)则与str1的(0x100001050)不同。可以得出结论:对于不可变字符串NSString,copy方法创建的新副本不会分配新的内存空间,而MutableCopy创建的新副本会分配新的内存空间。

NSMutableString:

 //main.m
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) {
@autoreleasepool { NSMutableString *str1 = [[NSMutableString alloc]initWithCapacity:];
NSMutableString *str2;
NSMutableString *str3;
NSMutableString *str4;
NSMutableString *str5;
NSMutableString *str6;
NSMutableString *str7; NSLog(@"@\"a\" address = %p", @"aaa");
NSLog(@"change before:");
str1 = [NSMutableString stringWithString:@"aaa"]; str2 = str1;
str3 = [NSMutableString stringWithString:str1];
str4 = [[NSMutableString alloc]initWithString:str1];
str5 = [[NSMutableString alloc]initWithCapacity:];
[str5 setString:str1];
str6 = [str1 copy];
str7 = [str1 mutableCopy]; NSLog(@"str1 = %@", str1); //输出str1内容
NSLog(@"str1 address = %p", str1); //输出str1内容所在的地址
NSLog(@"str2 = %@", str2); //输出str2内容
NSLog(@"str2 address = %p", str2); //输出str2内容所在的地址
NSLog(@"str3 = %@", str3); //输出str3内容
NSLog(@"str3 address = %p", str3); //输出str3内容所在的地址
NSLog(@"str4 = %@", str4); //输出str4内容
NSLog(@"str4 address = %p", str4); //输出str4内容所在的地址
NSLog(@"str5 = %@", str5); //输出str5内容
NSLog(@"str5 address = %p", str5); //输出str5内容所在的地址
NSLog(@"str6 = %@", str6); //输出str6内容
NSLog(@"str6 address = %p", str6); //输出str6内容所在的地址
NSLog(@"str7 = %@", str7); //输出str7内容
NSLog(@"str7 address = %p", str7); //输出str7内容所在的地址 NSLog(@" ");
NSLog(@"@\"bbb\" address = %p", @"bbb");
NSLog(@"change after:");
[str1 setString:@"bbb"];
NSLog(@"str1 = %@", str1); //输出修改后str1内容
NSLog(@"str1 address = %p", str1); //输出修改后str1内容所在地址
NSLog(@"str2 = %@", str2); //输出修改后str2内容
NSLog(@"str2 address = %p", str2); //输出修改后str2内容所在地址
NSLog(@"str3 = %@", str3); //输出修改后str3内容
NSLog(@"str3 address = %p", str3); //输出修改后str3内容所在地址
NSLog(@"str4 = %@", str4); //输出修改后str4内容
NSLog(@"str4 address = %p", str4); //输出修改后str4内容所在地址
NSLog(@"str5 = %@", str5); //输出修改后str5内容
NSLog(@"str5 address = %p", str5); //输出修改后str5内容所在地址
NSLog(@"str6 = %@", str6); //输出修改后str6内容
NSLog(@"str6 address = %p", str6); //输出修改后str6内容所在地址
NSLog(@"str7 = %@", str7); //输出修改后str7内容
NSLog(@"str7 address = %p", str7); //输出修改后str7内容所在地址 }
return ;
}
运行结果:

 1 -- ::03.191 copyTest[:] @"a" address = 0x100001068
-- ::03.192 copyTest[:] change before:
-- ::03.192 copyTest[:] str1 = aaa
-- ::03.192 copyTest[:] str1 address = 0x1002001d0
-- ::03.192 copyTest[:] str2 = aaa
-- ::03.192 copyTest[:] str2 address = 0x1002001d0
-- ::03.192 copyTest[:] str3 = aaa
-- ::03.193 copyTest[:] str3 address = 0x1002002f0
-- ::03.193 copyTest[:] str4 = aaa
-- ::03.193 copyTest[:] str4 address = 0x103000000
-- ::03.193 copyTest[:] str5 = aaa
-- ::03.193 copyTest[:] str5 address = 0x100200350
-- ::03.193 copyTest[:] str6 = aaa
-- ::03.193 copyTest[:] str6 address = 0x61616135
-- ::03.193 copyTest[:] str7 = aaa
-- ::03.193 copyTest[:] str7 address = 0x1002004c0
-- ::03.193 copyTest[:]
-- ::03.193 copyTest[:] @"bbb" address = 0x1000012a8
-- ::03.193 copyTest[:] change after:
-- ::03.193 copyTest[:] str1 = bbb
-- ::03.193 copyTest[:] str1 address = 0x1002001d0
-- ::03.193 copyTest[:] str2 = bbb
-- ::03.193 copyTest[:] str2 address = 0x1002001d0
-- ::03.193 copyTest[:] str3 = aaa
-- ::03.194 copyTest[:] str3 address = 0x1002002f0
-- ::03.194 copyTest[:] str4 = aaa
-- ::03.194 copyTest[:] str4 address = 0x103000000
-- ::03.194 copyTest[:] str5 = aaa
-- ::03.194 copyTest[:] str5 address = 0x100200350
-- ::03.194 copyTest[:] str6 = aaa
-- ::03.194 copyTest[:] str6 address = 0x61616135
-- ::03.194 copyTest[:] str7 = aaa
-- ::03.194 copyTest[:] str7 address = 0x1002004c0
Program ended with exit code:

结果分析:

一、改变str1前:

(1)str2 = str1这种简单的赋值只是str2引用了str1引用的地址,所以地址相同-0x1002001d0。

(2)str3,str4,str5都分配了新的地址空间,3者的地址都不相同。在它们得到了新分配的地址后,以可变字符串str1为参数进行了赋值,但实质上只是提取str1引用的地址里面的内容,即字符串aaa,它们之间没有任何联系。

(3)str6,str7是str1分别用copy和MutableCopy方法创建的新副本,它们引用的地址都和str1的不同,且str6和str7也不同。这里与可变字符串NSString有差异,可见上文结果分析(5)。这里得出结论:可变字符串NSMutableString,使用copy和MutableCopy创建的新副本都会为它们分配新的内存空间。

二、改变str1后:

(1)str1和str2引用了同一个地址,str2自然随着str1的改变而改变。str1的内容就是str2的内容。但是我们这次要观察的重点是,str1的内容变了,但它的地址没有改变,修改前后都是-0x1002001d0。这里与可变字符串NSString有差异,可见上文结果分析(3)。

(2)str3,str4,str5,str6,str7都与str1不同,所以内容不会发生改变。

我们再做一个测试:

 //main.m

 #import <Foundation/Foundation.h>

 int main(int argc, const char * argv[]) {
@autoreleasepool { NSString *str1 = @"a";
NSMutableString *str2;
NSMutableString *str3; NSMutableString *str4 = [NSMutableString stringWithString:@"a"];
NSString *str5;
NSString *str6; //一个不可变字符串str1使用copy和MutableCopy创建两个新副本给2个可变字符串str2和str3
str2 = [str1 copy];
str3 = [str1 mutableCopy]; //一个可变字符串str4使用copy和MutableCopy创建两个新副本给2个不可变字符串str5和str6
str5 = [str4 copy];
str6 = [str4 mutableCopy]; NSLog(@"str1 address = %p", str1);
NSLog(@"str2 address = %p", str2);
NSLog(@"str3 address = %p", str3);
NSLog(@"str4 address = %p", str4);
NSLog(@"str5 address = %p", str5);
NSLog(@"str6 address = %p", str6); }
return ;
}
 //运行结果:

 -- ::01.697 copyTest[:] str1 address = 0x100001050
-- ::01.698 copyTest[:] str2 address = 0x100001050
-- ::01.698 copyTest[:] str3 address = 0x100203980
-- ::01.698 copyTest[:] str4 address = 0x1002037b0
-- ::01.698 copyTest[:] str5 address = 0x6115
-- ::01.698 copyTest[:] str6 address = 0x100203a70
Program ended with exit code:

结果一目了然。不可变字符串的使用copy创建的新副本无论赋值给可变还是不可变字符串,都不会分配新的内存空间。

探讨NSString和NSMutableString的内存问题以及copy和MutableCopy两个方法的更多相关文章

  1. Objective-C学习篇06—NSString与NSMutableString

    NSString OC提供了定义字符串对象的方法,也就是将想要表达的字符串用一对双引号引起来,并在开头加上@.@是OC中的指令符,它告诉编译器@以后的内容为OC中的语法.比如@”Harbingwang ...

  2. Foundation框架-NSString和NSMutableString

    可变与不可变的字符串 --1-- Foundation框架介绍 1.1 框架介绍 --2-- NSString 2.1 NSString介绍及使用 2.2 NSString创建方式  2.3 从文件中 ...

  3. iOS基础-NSString及NSMutableString剖析

    一.NSString头文件 NSString : NSObject 实现协议: NSCopying/NSMutableCopying/NSSecureCoding 类别: //扩展类别 NSStrin ...

  4. 14.Object-C--浅谈Foundation框架字符串NSString 与NSMutableString

    OC的字符串时经常使用到的,今天我对于OC字符串做一个简单的总结,如果有错误之处,麻烦留言指正.感谢! NSString是一个不可变长度的字符串对象.表示它初始化以后,你不能改变该变量所分配的内存中的 ...

  5. 关于NSString和NSMutableString的相关用法和基本介绍

    Objective-C 中核心处理字符串的类是 NSString 与 NSMutableString ,这两个类最大的区别就是NSString 创建赋值以后该字符串的内容与长度不能在动态的更改,除非重 ...

  6. NSString和NSMutablestring,copy和strong(转载)

    1.http://www.cocoachina.com/ios/20150512/11805.html 2.http://blog.csdn.net/winzlee/article/details/5 ...

  7. NSString 与NSMutableString的区别

      NSString 与NSMutableString的区别    Suppose You have a code like this NSString *s = [[NSString alloc]  ...

  8. NSString和NSMutableString常用方法+NSArray常用代码 (转)

    常见的NSString和NSMutableString方法: NSString方法: [plain] view plaincopy   +(id) stringWithContentsOfFile:p ...

  9. OC之NSString、NSMutableString学习笔记 常用方法

    NSString篇: 1.字符串连接 NSString *beijing = @"北京"; NSString *welcome = [beijing stringByAppendi ...

随机推荐

  1. iOS5编程--ARC在工程上的相关设置

    在创建工程的时候,我们可以指定工程是否使用ARC技术,如下图 选中表示支持ARC, 在Beta5以前的版本中,不提供这个选项,非常麻烦. 如果是你拿到的工程,那么可以通过设置来改变,如下图所示 如果不 ...

  2. Elasticsearch从0.90到1.2的不兼容变化-系统和设置

      本文为官方文档的翻译加个人理解.作者翻译时,elasticsearch(下面简称es)的版本为1.2.1.   1.系统级别及设置方面 1.1 es启动时,默认是作为一个前台程序启动.如果你想让e ...

  3. poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)

    http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Subm ...

  4. springMVC+MyBatis+Spring+maven 整合(1)

    1.首先第一步.部署mybatis ; 1.1 下载myBatis MyBits前身是iBitis,相对于Hibernate而言,它是半自动化ORM框架.由于老板对性能要求的比较苛刻,不得不放弃我亲爱 ...

  5. 5.0:Spring-bean的加载

    内容来自<Spring深度解析>,之后的不一一复述! 在Spring中,最基本的IOC容器接口是BeanFactory - 这个接口为具体的IOC容器的实现作了最基本的功能规定 - 不管怎 ...

  6. 通过注册表查找oracle_home的位置

    运行regedit进入注册表 ctrl+f查找oracle_home

  7. C#查找子串在原串中出现次数

    提供的是一种思路,和具体语言无关. string test = "good good study day day up"; string r = test.Replace(&quo ...

  8. Aimp3的播放列表 按评分排序 落雨

    如图,添加评分选项,并保存,就可以在下图的选项里找到此选项,并按评分排序 效果图如下:还可以倒置,迅速使评分高的音乐排在播放列表的前面位置!! 转自百度知道: http://zhidao.baidu. ...

  9. linux下执行 ls,cat等一些命令报出 -bash: /bin/cat: Cannot allocate memory 有没解决的方法

    环境变量配置出错了cd -- 进入用户目录vim .bash_profile删除以前PATH这一行,把下面的粘帖进去PATH=$PATH:$HOME/bin:/root:/root/snapshot/ ...

  10. UR #13 Yist

    第一次打UR,打了一个半小时就弃疗了QAQ 这是我唯一一道考试的时候做出来的题目,其他两道连暴力都懒得写了 很容易发现对于每个要删除的点 我们找到左边第一个比他小的不用删除的点,右边第一个比他小的不用 ...