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. iOS 获取手机的型号,系统版本,软件名称,软件版本

    转载自:http://www.2cto.com/kf/201210/162333.html   网上搜索出来的,记录下来以后使用方便: [java]//手机序列号      NSString* ide ...

  2. Unity3d之Socket UDP协议

    原文地址:http://blog.csdn.net/dingkun520wy/article/details/49201245 (一)Socket(套接字)UDP协议的特点 1.是基于无连接的协议,没 ...

  3. crontab定时任务中文乱码问题

    手动执行都很正常的的脚本,添加到定时任务中日志文件全是乱码经过多方查证终于找到了原因! crontab启动的任务没有获取系统的环境变量,导致中文乱码解决办法:   在执行的脚步中添加编码方式或者添加对 ...

  4. 1052: [HAOI2007]覆盖问题 - BZOJ

    Description 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小 ...

  5. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

  6. PAT-乙级-1045. 快速排序(25)

    1045. 快速排序(25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CAO, Peng 著名的快速排序算法里有一个经典的划分 ...

  7. C++中的构造函数,拷贝构造函数和赋值运算

    关于C++中的构造函数,拷贝构造函数和赋值运算,以前看过一篇<高质量C++/C编程指南>的文章中介绍的很清楚,网上能搜索到,如果想详细了解这方面的知识可以参看一下这篇文章. 常见的给对象赋 ...

  8. 关于PYTHON的反射,装饰的练习

    从基本概念,简单例子才能慢慢走到高级一点的地方. 另外,PYTHON的函数式编程也是我很感兴趣的一点. 总体而言,我觉得OOP可以作大的框架和思路,FP能作细节实现时的优雅牛X. ~~~~~~~~~~ ...

  9. HDU1411+四面体的体积

    用cos sin各种乱搞之后 求出一个公式.. 但是怕精度损失厉害,还是暂且贴个公式的,copy别人的.. #include<stdio.h> #include<math.h> ...

  10. NPOI.dll学习

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. 简介 编辑 使用 NPOI 你就可以在没有安装 Office 或者相应环 ...