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. Ubuntu下Sublime Text 3无法输入中文的解决方案

    1. 保存下面的代码到文件sublime_imfix.c中: /* * sublime-imfix.c * Use LD_PRELOAD to interpose some function to f ...

  2. linux内核驱动中_IO, _IOR, _IOW, _IOWR 宏的用法与解析(引用)

    在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值.cmd除了可区别数字外,还包含有助于处理的几种相应信息. cmd的大小为 32位,共分 4 个 ...

  3. EXTJS 4.2 资料 控件之textfield文本框加事件的用法

    { xtype: "textfield", width: 100, id: "txtGroupName", name: "txtGroupName&q ...

  4. (转)关于linux中内核编程中结构体的赋值操作(结构体指定初始化)

    网址:http://blog.chinaunix.net/uid-24807808-id-3219820.html 在看linux源码的时候,经常会看到类似于下面的结构体赋值的代码: struct d ...

  5. 实时数据处理环境搭建flume+kafka+storm:2.flume 安装

    1.  解压  tar -zxvf     2.配置       拷贝配置文件 :cp flume-conf.properties.template flume-conf.properties     ...

  6. linux学习笔记(1)-文件处理相关命令

    列出文件和目录 ls (list) #ls 在终端里键入ls,并回车,就会列出当前目录的文件和目录,但是不包括隐藏文件和目录 #ls -a 列出当前目录的所有文件 #ls -al 列出当前目的所有文件 ...

  7. case class inheritance

    Scala 禁止case class inheritance case class Person(name: String, age: Int) case class FootballPlayer(n ...

  8. UIcollectionView的使用(首页的搭建1)

    今天做一个首页的效果:  首页是用UICollectionView做的.下面我来结合首页的效果介绍一下: 一.创建基类继承自UIViewController 01 创建基类继承自UIViewContr ...

  9. 【mysql的设计与优化专题(5)】慢查询详解

    查询mysql的操作信息 show status -- 显示全部mysql操作信息 show status like "com_insert%"; -- 获得mysql的插入次数; ...

  10. HDU1875——畅通工程再续(最小生成树:Kruskal算法)

    畅通工程再续 Description相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当 ...