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. 移动APP学习笔记一

    登录 ●登录用户名和密码错误时,界面有提示信息 ●用户主动退出登录后,下次启动APP时,应该进入登录界面 ●对于支持自动登录的APP,数据交换时  ,是否能自动登录成功且数据库操作无误 ●密码更改后, ...

  2. NGUI系列教程八(监听NGUI的事件方法)

    NGUI事件的种类很多,比如点击.双击.拖动.滑动等等,他们处理事件的原理几乎万全一样,本文只用按钮来举例. 1.直接监听事件 把下面脚本直接绑定在按钮上,当按钮点击时就可以监听到,这种方法不太好很不 ...

  3. C# Windows - TabControl

    TabControl控件的属性 - 一般用于控制TabPages对象容器的外观,特别是显示的选项卡的外观 属性 说明 Alignment 控制选项卡在选项卡控件的什么位置显示 Appearance 控 ...

  4. iOS 的 Gif 渲染引擎 FLAnimatedImage-b

    公司的项目有个首页加载一张2M左右的git图,刚做的时候是使用的SDWebImage里面的方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name; ...

  5. OpenSessionInViewFilter 的配置及替代方案(转)

    鸣谢:http://justsee.iteye.com/blog/1174999,http://blog.csdn.net/sunsea08/article/details/4545186 Sprin ...

  6. Objective C 四舍五入,float处理

    NSLog(@"平方:%.f", pow(3,2) ); //result 9 NSLog(@"上舍入:%.f", ceil(3.000000000001)); ...

  7. DIV中TABLE居的2种方式

    <html><head><title>测试页面</title></head><body><div width=" ...

  8. Recommender Systems协同过滤

    第一部分是学习ID3时候积累的. 一.以前写的基础知识 1.信息:是用来消除不确定性的度量,信息量的大小,由所消除的不确定性的大小来计量(香农). 2.由于不确定性是由随机性引起的,所以用概率来描述和 ...

  9. select框宽度与高度设置(实用版)

    在IE中只能使用 font-size: 限制 select 的高度.   同时使用 width:200px 限制宽度   size="20" 表示最多显示20个选项,超过20的需要 ...

  10. 数据关联分析 association analysis (Aprior算法,python代码)

    1基本概念 购物篮事务(market basket transaction),如下表,表中每一行对应一个事务,包含唯一标识TID,和购买的商品集合.本文介绍一种成为关联分析(association a ...