nsstring内存占用率多少合适多少内存

大部分的时候NSString的属性都是copy,那copy与strong的情况下到底有什么区别呢?
@property&(retain,nonatomic)&NSString&*rS
@property&(copy,&nonatomic) &&NSString&*cS
- (void)test:
& &&NSMutableString&*mStr = [NSMutableStringstringWithFormat:@&abc&];
& &&self.rStr&& = mS
& &&self.cStr&& & = mS
& &&NSLog(@&mStr:%p,%p&,& mStr,&mStr);
& &&NSLog(@&retainStr:%p,%p&,&_rStr,
& &&NSLog(@&copyStr:%p,%p&,& &_cStr,
假如,mStr对象的地址为0x11,也就是0x11是@“abc”的首地址,mStr变量自身在内存中的地址为0x123;
当把mStr赋值给retain的rStr时,rStr对象的地址为0x11,rStr变量自身在内存中的地址为0x124;rStr与mStr指向同样的地址,他们指向的是同一个对象@“abc”,这个对象的地址为0x11,所以他们的值是一样的。
当把mStr赋值给copy的cStr时,cStr对象的地址为0x22,cStr变量自身在内存中的地址0x125;cStr与mStr指向的地址是不一样的,他们指向的是不同的对象,所以copy是深复制,一个新的对象,这个对象的地址为0x22,值为@“abc”。
如果现在改变mStr的值:
& &&[mStr&appendString:@&de&];
& &&NSLog(@&retainStr:%@&,&&_rStr);
& &&NSLog(@&copyStr:%@&,& &&_cStr);
使用retain的字串rStr的值:@&abcde&,
而使用copy的字串cStr的值:@&abc&,
所以,如果一般情况下,我们都不希望字串的值跟着mStr变化,所以我们一般用copy来设置string的属性。
如果希望字串的值跟着赋值的字串的值变化,可以使用strong,retain。
注意:上面的情况是针对于当把NSMutableString赋值给NSString的时候,才会有不同,如果是赋值是NSString对象,那么使用copy还是strong,结果都是一样的,因为NSString对象根本就不能改变自身的值,他是不可变的。
把一个对象赋值给一个属性变量,当这个对象变化了,如果希望属性变量变化就使用strong属性,如果希望属性变量不跟着变化,就是用copy属性。
由此可以看出:
对源头是NSMutableString的字符串,retain仅仅是指针引用,增加了引用计数器,这样源头改变的时候,用这种retain方式声明的变量(无论被赋值的变量是可变的还是不可变的),它也会跟着改变;而copy声明的变量,它不会跟着源头改变,它实际上是深拷贝。
对源头是NSString的字符串,无论是retain声明的变量还是copy声明的变量,当第二次源头的字符串重新指向其它的地方的时候,它还是指向原来的最初的那个位置,也就是说其实二者都是指针引用,也就是浅拷贝。
另外说明一下,这两者对内存计数的影响都是一样的,都会增加内存引用计数,都需要在最后的时候做处理。
其实说白了,对字符串为啥要用这两种方式?我觉得还是一个安全问题,比如声明的一个NSString *str变量,然后把一个NSMutableString *mStr变量的赋值给它了,如果要求str跟着mStr变化,那么就用如果str不能跟着mStr一起变化,那就用copy。而对于要把NSString类型的字符串赋值给str,那两都没啥区别。不会影响安全性,内存管理也一样。
本文已收录于以下专栏:
相关文章推荐
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?
ARC下 NSString属性什么时候用copy,什么时候用strong?我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有...
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?让我们先来看...
NSString属性什么时候用copy,什么时候用strong?
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有...
大部分的时候NSString的属性都是copy,那copy与strong的情况下到底有什么区别呢?
@property (retain,nonatomic) NS...
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?让我们先来看...
关于 copy strong
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?让我们先来看...
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?让我们先来看...
转载自南峰子
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用co...
他的最新文章
讲师:王哲涵
讲师:韦玮
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)1.内存管理的范围:所有的OC对象(继承自NSObject类)
2.为什么内存管理只管理OC对象?程序运行时内存分为五大部分:从下往上:代码区,数据区,BSS段,以及堆区,栈区。其中前三个区域的数据,程序启动的时候占用内存区间,无法进行管理。栈区的数据由系统自动管理,不需要进行管理。栈区从高地址向低地址分配,堆区从低地址向高地址分配。堆区主要是OC中的实例对象,内存管理主要是对堆区进行管理,所以内存管理主要进行的OC对象的管理。
3.如何进行内存 管理?通过操作对象的引用计数器。
4.什么是引用计数器? &1)每个对象都有自己的引用计数器。2)它是一个整数(int,占用4个字节)。3)从字面上,可以理解为“对象被引用的次数”。4)也可以理解为:当前有多少个人正在使用这个对象。
5.引用计数器的作用?系统通过“引用计数器”来判断当前对象是否可以被释放。
6.对象的引用计数器的操作方式? & 1)retain & 使计数器+1 &。2)release &使计数器-1。3)retainCount &返回当前计数器的值。当为0的时候无法使用,因为对象已被释放。
7.dealloc 方法。 1)当对象即将被销毁的时候,系统自动给对象发送一条dealloc消息,因此,从dealloc方法有没有被调用,可以判断出对象是否被释放。2)可以重写dealloc方法,并且在重写的最后,要调用父类的dealloc方法,也就是[super dealloc],注意:必须放在最后。3)dealloc方法无法被直接调用,只能系统自动调用。
8.野指针/空指针/僵尸对象。&
& 1)僵尸对象:已经被销毁的对象(不能再使用的对象)
& 2)野指针:指向僵尸对象的指针。
& 3)控制帧:没有指向内存空间的指针。存放的是nil,也就是0.
9.Xcode中有僵尸对象检测机制,开启之后,会防止程序对僵尸对象进行操作。
10.多对象的内存管理:
& &-(void) setCar:(Car * ) car {
& & & & & & _car=
-(void) drive{&
& & & & & [_car Run];
& & & & & NSLog(@& %@在跑&, _car.Name);
错误实例1):对象已经释放,再次去使用对象的方法。
[ car & release]; &//此处释放了car 对象
[ p &drive]; & // &此处p 未被释放,但是车已被释放,调用人的方法,造成了野指针car &访问僵尸对象 。
错误实例2):给p.car 设置不同对象造成原对象内存泄漏,原对象没有被释放。
错误实例3):给p.car设置同一对象,造成对象变为僵尸对象,以及本对象的指针成为了野指针。
正确的方法:在set 以及dealloc方法中管理对象的引用计数器:
-(void) &setCar:(Car *) car{
& & & & if(_car!=car)
& & & & & & & &[ _car release];
& & & & & & & &_car=[car &retain]; &
-(void) dealloc:{
& & & & & & [ _car release ];
& & & & & &[ super &dealloc ] ;
11. 苹果官方内存管理的基本原则:
& &1) 谁创建谁release ,如果你通过alloc,new 或 copy ,mutableCopy 创建了一个对象,那么必须调用 release 或者autorelease &。
& &2)谁retain 谁release,只要你调用了retain ,就必须调用一次release 。
12.@property 的修饰关键字:
& &1)控制set 方法的内存管理 :retain :release 旧值,retain 新值(用于OC对象) ,要配合nonatomic 使用。 & 比如: @property (nonatomic , retain) &car ;
& & & & & & & & & & & & & & & & & & & & & & & & & & & & assign:直接赋值,不做任何内存管理(默认,用于非OC对象类型),不会进行retain。
& & & & & & & & & & & & & & & & & & & & & & & & & & & & copy:release 旧值 ,copy 新值 (一般用于NSString *);
& &2)控制是否生成set方法: readwrite: 同时生成get 和set 方法(默认) &; readonly: 只读,不生成set方法,只生成get方法。
& &3)多线程管理:atomic:性能低(默认);nonatomic:性能高,(为IOS系统开发时建议使用,为mac开发可以使用atomic);
& &4)控制get和set 方法的名称: setter: 这是set方法的名称,注意要有冒号;getter: 设置get方法的名称,冒号。
13.@class的用法:
& & 1)为什么要使用@class? &主要是用于解决循环引入的问题,比如A引入B,B引入A,这时用#import 会造成循环以来,使用@class则不会。注意:使用@class之后,要在.m文件中引入 .h文件,比如:A的.m文件中,要引入B.h文件。
& & 2)和import的区别:主要就是解决循环依赖的问题。
14.内存管理时的循环retain问题。
& & &比如,A中有一个B 实例对象,B中有一个A实力对象,这时如果把A赋值给B,B赋值给A,如果A,B都是用retain ,会造成程序结束的时候A,B引用计数仍为1,AB无法释放,内存泄漏。
& & 如果此时A使用retain,B使用assign,则不会造成这种现象,注意:assign的dealloc中不需要release。这是推荐使用方法。另外的方法是:在最后对A或者B 再次进行释放,此处需要注意顺序问题,必须是在程序的最后。
15.NSString的内存管理问题。
& & 初始化字符串的时候,直接赋值 @&abc&,stringWithString ,alloc &initWithString这三种方法中,@&abc& &存放在常量池。重复赋值,不会重新分配内存空间。
& & &注意:常量区的引用计数是lu的最大值。
& & stringWithFormat &alloc &initWithFormat ,存放的地址为堆区。 & & NSString 不需要我们进行内存管理,Foundation框架会自动帮我们管理。
本文已收录于以下专栏:
相关文章推荐
★腾 讯 备 案 电 话【<7551】抽 奖 二 线【9<0586】活 动 热线★抽奖腾讯备案电话【-7551】抽 奖 二 线【...
以下Objective-c简称OC
从事java开发的程序员们都知道,在java中interface是接口的意思,java中类是用class声明,接口用interface声明,是两个独立的部分,只有...
NSString等Foundation框架提供的类的内存管理
    (1)字符串的常量池(在数据区) 
    (2)
        NSString *str1 = @“abc”;
  ...
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1.   内存管理的范围
1)  管理任何继承NSObject的对象,对其他基本...
本文是我自己在学习的时候总结的一些东西,现在共享给大家,希望大家共同进步!
IOS开发中的MRC内存管理中七大知识点___________每个对象都有自己的引用计数器。 在MRC内存管理模式下,引用计数器计算机是无法自动操作的。
向对象发送[对象 retainCount];该...
这几天在看Glibc 内存管理模块的内容,感觉收获颇多,在此做个简单的总结,以便知识点回顾。
先介绍一下相关的背景。有个项目组在研发一个类似数据库的NoSql 系统时,遇到了Glibc 内存暴增问题...
动态内存管理核心:
首先,我们来重载一下operator new ();进行预处理,给我们打印一些有用的 信息,比如:当前定位的行号,开辟空间的大小(方便我们对于内存泄漏的检查)#include...
我们都知道每个类在创造实例的时候都会在内存中给它划分一片区域来存放信息,然后对象名作为指针指向该内存空间,如果这个对象不再使用,这片内存区域就会被系统回收,删掉原内容或覆盖上其他内容,OC...
Linux内存管理机制:
1、             为解决以下几个问题:
  如何使进程的地址空间隔离;如何提高内存的使用效率;如何解决程序运行时的重定...
他的最新文章
讲师:王哲涵
讲师:韦玮
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)plist文件以文本形式存储,一个字符占用一个字节,外加plist文件的头部,占用空间就是所有的字符数。
加载到内存所占空间与文件大小一致。
比如下方一个字符串是300个字符。10000个对象存储到文件中,文件大小为3.2MB。加载到内存所占空间也是3.2MB
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i=0; i&10000; i++) {
[array addObject:@"adsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfadsjadslkjfksdajfklasjdkfkalsdklfa300"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = @"1.plist";
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSLog(@"path is : %@",filePath);
[array writeToFile:filePath atomically:YES];
NSArray *arr2 = [NSArray arrayWithContentsOfFile:filePath];
self.arr2 = arr2;
NSLog(@"");
阅读(...) 评论()探讨NSString和NSMutableString的内存问题以及copy和MutableCopy两个方法
时间: 18:38:12
&&&& 阅读:54
&&&& 评论:
&&&& 收藏:0
NSString:
1 //main.m
2 #import &Foundation/Foundation.h&
4 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 2016-06-05 14:29:49.451 copyTest[1526:60199] @"aaa" address = 0x
2 2016-06-05 14:29:49.452 copyTest[1526:60199] change before:
3 2016-06-05 14:29:49.452 copyTest[1526:60199]
str1 = aaa
4 2016-06-05 14:29:49.452 copyTest[1526:60199]
str1 address = 0x
5 2016-06-05 14:29:49.453 copyTest[1526:60199]
str2 = aaa
6 2016-06-05 14:29:49.453 copyTest[1526:60199]
str2 address = 0x
7 2016-06-05 14:29:49.453 copyTest[1526:60199]
str3 = aaa
8 2016-06-05 14:29:49.453 copyTest[1526:60199]
str3 address = 0x
9 2016-06-05 14:29:49.453 copyTest[1526:60199]
str4 = aaa
10 2016-06-05 14:29:49.453 copyTest[1526:60199]
str4 address = 0x
11 2016-06-05 14:29:49.453 copyTest[1526:60199]
str5 = aaa
12 2016-06-05 14:29:49.453 copyTest[1526:60199]
str5 address = 0x
13 2016-06-05 14:29:49.453 copyTest[1526:60199]
str6 = aaa
14 2016-06-05 14:29:49.453 copyTest[1526:60199]
str6 address = 0x
15 2016-06-05 14:29:49.453 copyTest[1526:60199]
16 2016-06-05 14:29:49.453 copyTest[1526:60199] @"bbb" address = 0x
17 2016-06-05 14:29:49.453 copyTest[1526:60199] change after:
18 2016-06-05 14:29:49.453 copyTest[1526:60199]
str1 = bbb
19 2016-06-05 14:29:49.453 copyTest[1526:60199]
str1 address = 0x
20 2016-06-05 14:29:49.453 copyTest[1526:60199]
str2 = aaa
21 2016-06-05 14:29:49.453 copyTest[1526:60199]
str2 address = 0x
22 2016-06-05 14:29:49.454 copyTest[1526:60199]
str3 = aaa
23 2016-06-05 14:29:49.454 copyTest[1526:60199]
str3 address = 0x
24 2016-06-05 14:29:49.454 copyTest[1526:60199]
str4 = aaa
25 2016-06-05 14:29:49.454 copyTest[1526:60199]
str4 address = 0x
26 2016-06-05 14:29:49.454 copyTest[1526:60199]
str5 = aaa
27 2016-06-05 14:29:49.454 copyTest[1526:60199]
str5 address = 0x
28 2016-06-05 14:29:49.454 copyTest[1526:60199]
str6 = aaa
29 2016-06-05 14:29:49.454 copyTest[1526:60199]
str6 address = 0x
30 2016-06-05 14:29:49.454 copyTest[1526:60199]
@"aaa" address = 0x
31 Program ended with exit code: 0
结果分析:
(1)在定义str1时就先把字符串@"aaa"赋值给str1,输出时 @"aaa"和str1的地址相同,都是&0x&。
(2)接着以三种不同的方式将str1赋值给str2, str3, str4
(3)再次给str1赋值,这次将字符串@"bbb"赋值给str1。 不同的是,我们在赋值前先输出一次字符串@"bbb"的地址,根据输出结果发现又与str1的地址相同,但地址已经发生变化&0x --&&0x&。由此可以发现,不可变字符串NSString在第一次赋值时,指向一个内存空间,当它被再次被赋值于不同的字符串时,它会指向另一个内存空间,这与可变字符串NSMutableString不同(稍后会对NSMutableString进行测试)。
不可变字符串NSString的&不可变&我理解为是它引用的地址的那个内容不能改变,但是它引用的地址是可以改变的,有点拗口:
我把aaa赋值给str1,没有改变aaa这个字符串,当然也没有改变str1。当我再次赋值bbb给str1时,似乎是str1引用的地址-0x&的内容(即aaa)改变成了bbb,其实不然。事实上我们是改变了str1引用的地址来实现这种&假象&的。str1的引用地址已经由&0x(含有字符串aaa的地址)变为&0x(含有字符串bbb的地址)。我们通过最后一行输出结果:字符串aaa的地址仍是&0x,就可以知道在str1被bbb重新赋值的这个过程中aaa没有发生任何改变。
(4)str2,str3,str4的结果就很清晰了。他们都只是引用了aaa赋值给str1时的地址。所以他们都引用这个地址0x,这个地址里面的内容也就是aaa了。
(5)str5,str6分别是str1使用copy和MutableCopy方法创建的副本。&根据输出可以看到在str1改变前,通过copy创建的副本str5引用的地址,与str1引用的地址相同-0x;MutableCopy创建的副本引用的地址(0x)则与str1的(0x)不同。可以得出结论:对于不可变字符串NSString,copy方法创建的新副本不会分配新的内存空间,而MutableCopy创建的新副本会分配新的内存空间。
NSMutableString:
1 //main.m
2 #import &Foundation/Foundation.h&
4 int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableString *str1 = [[NSMutableString alloc]initWithCapacity:0];
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:0];
[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内容所在地址
运行结果: 1 2016-06-05 15:08:03.191 copyTest[1709:76858] @"a" address = 0x
2 2016-06-05 15:08:03.192 copyTest[1709:76858] change before:
3 2016-06-05 15:08:03.192 copyTest[1709:76858] str1 = aaa
4 2016-06-05 15:08:03.192 copyTest[1709:76858] str1 address = 0x
5 2016-06-05 15:08:03.192 copyTest[1709:76858] str2 = aaa
6 2016-06-05 15:08:03.192 copyTest[1709:76858] str2 address = 0x
7 2016-06-05 15:08:03.192 copyTest[1709:76858] str3 = aaa
8 2016-06-05 15:08:03.193 copyTest[1709:76858] str3 address = 0x
9 2016-06-05 15:08:03.193 copyTest[1709:76858] str4 = aaa
10 2016-06-05 15:08:03.193 copyTest[1709:76858] str4 address = 0x
11 2016-06-05 15:08:03.193 copyTest[1709:76858] str5 = aaa
12 2016-06-05 15:08:03.193 copyTest[1709:76858] str5 address = 0x
13 2016-06-05 15:08:03.193 copyTest[1709:76858] str6 = aaa
14 2016-06-05 15:08:03.193 copyTest[1709:76858] str6 address = 0x
15 2016-06-05 15:08:03.193 copyTest[1709:76858] str7 = aaa
16 2016-06-05 15:08:03.193 copyTest[1709:76858] str7 address = 0x
17 2016-06-05 15:08:03.193 copyTest[1709:76858]
18 2016-06-05 15:08:03.193 copyTest[1709:76858] @"bbb" address = 0x
19 2016-06-05 15:08:03.193 copyTest[1709:76858] change after:
20 2016-06-05 15:08:03.193 copyTest[1709:76858] str1 = bbb
21 2016-06-05 15:08:03.193 copyTest[1709:76858] str1 address = 0x
22 2016-06-05 15:08:03.193 copyTest[1709:76858] str2 = bbb
23 2016-06-05 15:08:03.193 copyTest[1709:76858] str2 address = 0x
24 2016-06-05 15:08:03.193 copyTest[1709:76858] str3 = aaa
25 2016-06-05 15:08:03.194 copyTest[1709:76858] str3 address = 0x
26 2016-06-05 15:08:03.194 copyTest[1709:76858] str4 = aaa
27 2016-06-05 15:08:03.194 copyTest[1709:76858] str4 address = 0x
28 2016-06-05 15:08:03.194 copyTest[1709:76858] str5 = aaa
29 2016-06-05 15:08:03.194 copyTest[1709:76858] str5 address = 0x
30 2016-06-05 15:08:03.194 copyTest[1709:76858] str6 = aaa
31 2016-06-05 15:08:03.194 copyTest[1709:76858] str6 address = 0x
32 2016-06-05 15:08:03.194 copyTest[1709:76858] str7 = aaa
33 2016-06-05 15:08:03.194 copyTest[1709:76858] str7 address = 0x
34 Program ended with exit code: 0
&结果分析:
一、改变str1前:
(1)str2 = str1这种简单的赋值只是str2引用了str1引用的地址,所以地址相同-0x。
(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的内容变了,但它的地址没有改变,修改前后都是-0x。这里与可变字符串NSString有差异,可见上文结果分析(3)。
(2)str3,str4,str5,str6,str7都与str1不同,所以内容不会发生改变。
我们再做一个测试:
1 //main.m
3 #import &Foundation/Foundation.h&
5 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);
1 //运行结果:
3 2016-06-05 16:57:01.697 copyTest[2175:117425] str1 address = 0x
4 2016-06-05 16:57:01.698 copyTest[2175:117425] str2 address = 0x
5 2016-06-05 16:57:01.698 copyTest[2175:117425] str3 address = 0x
6 2016-06-05 16:57:01.698 copyTest[2175:117425] str4 address = 0x
7 2016-06-05 16:57:01.698 copyTest[2175:117425] str5 address = 0x6115
8 2016-06-05 16:57:01.698 copyTest[2175:117425] str6 address = 0x
9 Program ended with exit code: 0
结果一目了然。不可变字符串的使用copy创建的新副本无论赋值给可变还是不可变字符串,都不会分配新的内存空间。标签:
&&国之画&&&& &&&&chrome插件&&
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 win10内存占用多少 的文章

 

随机推荐