NSString的Copy与内存分配
来源:互联网 发布:aspnet源码 编辑:程序博客网 时间:2024/05/21 13:58
原文链接:http://tutuge.me/2015/02/18/NSString%E7%9A%84Copy%E4%B8%8E%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/
前言
不管是用什么语言开发,字符串应该算是用的最多的了。在Objective-C中,字符串类是NSString,以及其子类NSMutableString等。所以,对于字符串类,编程语言、编译器等往往会做特殊处理。下面我就说说我自己在项目中发现的NSString的“奇怪”的地方。
字符串常量,copy,mutableCopy
Example
先看看如下面的代码,猜猜会输出什么:
NSString *str1 = @"abc";NSString *str2 = @"abc";NSString *str3 = [[NSString alloc] initWithString:@"abc"];NSString *str4 = [str1 copy];NSString *str5 = [str1 mutableCopy];//输出内存中的地址NSLog(@"str1: %p", str1);NSLog(@"str2: %p", str2);NSLog(@"str3: %p", str3);NSLog(@"str4: %p", str4);NSLog(@"str5: %p", str5);
直接给出结果:
//地址值由运行时决定,不唯一str1: 0x10cd12040str2: 0x10cd12040str3: 0x10cd12040str4: 0x10cd12040str5: 0x7f874b508350 //mutable copy
看,是不是很“神奇”。
简单解释
NSString是“不可变(immutable)”的类型,这个是关键。
代码中的“@”开头的字符串,其实就是一个字符串常量,运行时会检测这个字符串是否已经存在,存在的话,就直接将这个字符串的地址赋给变量;不存在的话,则创建,再赋值。
第一行: “abc”字符串不存在,创建,取得字符串地址“0x10cd12040”,赋给str1.
第二行: “abc”字符串已经存在,直接将地址“0x10cd12040”赋给str2.
第三行: (记住,NSString是不可变的)alloc并不会分配新的内存,直接将字符串地址“0x10cd12040”赋给str3.
第四行: copy,既然是不可变的,也就没有必要分配新内存,直接将地址“0x10cd12040”赋给str4.
第五行: mutableCopy其实就是创建一个NSMutableString的实例,既然是“可变(mutable)”的类型了,当然要分配新的内存,所以,字符串的地址也变成新的“0x7f874b508350”。
可以这么说,编译器、runtime充分利用了NSString是“不可变(immutable)”类型这个特点,只要字符串内容一致,就不会分配新的内存储存,字符串在程序中使用量非常大,这么做无疑可以大大节省内存,提升性能。
Property 和 NSString
先来看看一个UserEntity类:
//UserEntity.h@interface UserEntity : NSObject <NSCopying>@property(strong, nonatomic) NSString *name;@end
只有一个名为name的NSString类型Property。
相信大家对这个不陌生吧。一般我们的应用中会有很多Entity类型,每个Entity类里面肯定避免不了有许多NSString的字符串类型。这里的name的属性是:strong和nonatomic,strong表明name要“持有”一份name所指的字符串的引用,nonatomic表示property类型不用加锁。
接着咱们看看下面的代码:
UserEntity *userEntity = [UserEntity new]; //创建mutable类型的字符串NSMutableString *showName = [[NSMutableString alloc] initWithString:@"tutuge"]; //先保存“tutuge”字符串到userEntity的nameuserEntity.name = showName; //修改showName[showName appendString:@" blog"]; //输出userEntity的name属性NSLog(@"Name: %@", userEntity.name);
猜猜会输出什么?
Name: tutuge blog
看,我们明明是保存的“tutuge”,怎么到后面输出的是“tutuge blog”?
让NSString类型的Property为Copy型
因为name的Property属性是strong的,所以赋值后,它跟showName均指向同一个NSMutableString实例,如下:
所以改变了showName,当然name输出的值也就变了。
这个时候,name的property属性就不能是strong了,应该是copy,如下:
//UserEntity.h@interface UserEntity : NSObject <NSCopying>@property(copy, nonatomic) NSString *name;@end
这样的话,当“userEntity.name = showName;”这句运行后,内存布局如下:
这样,就避免了这个问题。
总结
很所时候,代码并不是看上去那样“运行”的,多试试,多查阅资料,就能了解其中的奥秘了~
- NSString的Copy与内存分配
- NSString 的copy 与 mutableCopy
- NSString的内存分配及管理
- NSString的内存分配及管理
- NSString的内存分配及管理
- NSString的内存分配及管理
- NSString字符串创建的内存分配
- NSString的copy 属性
- 声明NSString属性用 Copy 与 strong 的区别
- 使用copy与strong声明NSString属性的区别
- OC中与copy有关的那些事 一 (copy与声明NSString属性 : strong/copy 的关系)
- NSString 的copy和retain
- 体会NSString的copy属性
- NSString的strong和copy
- 堆栈内存分配与内存池内存分配的区别
- 内存的分配与释放
- 内存的分配与释放
- 内存的分配与释放
- POJ 2184 Cow Exhibition
- PhoneGap项目导入到Androidstudio指南
- 1055. The World's Richest (25)
- Vim命令合集
- Android中MalformedURLException的解决
- NSString的Copy与内存分配
- hdu 1458 bfs模板化写法
- android 菜单栏高度
- Android进程间通讯——Clipboard(剪切板)
- 一次ora 12537问题的解决
- 分布式系统架构中的中间件
- asp.net mvc4 添加分区出现错误 找到多个与名为“home”的控制器匹配的类型
- linux mysql 操作命令
- PhoneGap 4.2.0-0.24.2(Cordova 4.3.0)插件指南