美文网首页
iOS字符串深拷贝(内容拷贝),浅拷贝(指针拷贝)以及字符串st

iOS字符串深拷贝(内容拷贝),浅拷贝(指针拷贝)以及字符串st

作者: 就叫我Kuzan | 来源:发表于2017-06-19 15:37 被阅读30次

本文很大部分借鉴:[http://www.cnblogs.com/tandaxia/p/4475410.html]
自己动手写一下并记录来加深对深拷贝,浅拷贝的理解

一、 属性修饰符strong、copy修饰字符串的区别

先创建一个strTest类定义属性

#import <Foundation/Foundation.h>
@interface stringTest : NSObject
@property (nonatomic, strong) NSString *strStrong;
@property (nonatomic, copy) NSString *strCopy;
@property (nonatomic, strong) NSMutableString *strMutableStrong;
@property (nonatomic, copy) NSMutableString *strMutableCopy;
@end

然后测试代码

stringTest *test = [[stringTest alloc] init];
NSLog(@"-----给字符串属性赋值不可变字符串------");
NSString *string1 = @"str1";
[test setStrStrong:string1];

test.strCopy = string1;
test.strMutableStrong = string1;
test.strMutableCopy = string1;
NSLog(@"------赋值str1的log------");
NSLog(@"string1: %p %@",string1,string1);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@\n\n", test.strMutableCopy,test.strMutableCopy);

string1 = @"str2";

NSLog(@"------- 改变原字符串为str2后log -------");
NSLog(@"string1: %p %@",string1,string1);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@", test.strMutableCopy,test.strMutableCopy);

NSLog(@"-----------------------------------------------华丽分割线--------------------------------------------");
NSLog(@"-------------给字符串属性赋值可变字符串-----------------");

NSMutableString *MuString = [[NSMutableString alloc] initWithString:@"MuString"];
[test setStrStrong:MuString];
[test setStrCopy:MuString];
test.strMutableStrong = MuString;
test.strMutableCopy = MuString;

NSLog(@"------赋值MuString的log------");
NSLog(@"MuString: %p %@",MuString,MuString);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@\n\n", test.strMutableCopy,test.strMutableCopy);

[MuString appendString:@"_test"];
NSLog(@"------- 改变原字符串为MuString_test后log -------");
NSLog(@"MuString: %p %@",MuString,MuString);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@", test.strMutableCopy,test.strMutableCopy);

打印结果

2017-06-19 14:03:08.656 bibi[12436:131119] -----给字符串属性赋值不可变字符串------
2017-06-19 14:03:08.656 bibi[12436:131119] ------赋值str1的log------
2017-06-19 14:08:22.727 bibi[12746:135927] string1: 0x1001c40a0 str1
2017-06-19 14:03:08.656 bibi[12436:131119] test.strStrong: 0x1094810a0 str1
2017-06-19 14:03:08.656 bibi[12436:131119] test.strCopy: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strMutableStrong: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strMutableCopy: 0x1094810a0 str1

2017-06-19 14:03:08.657 bibi[12436:131119] ------- 改变原字符串为str2后log -------
2017-06-19 14:08:22.728 bibi[12746:135927] string1: 0x1001c4180 str2
2017-06-19 14:03:08.657 bibi[12436:131119] test.strStrong: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strCopy: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strMutableStrong: 0x1094810a0 str1
2017-06-19 14:03:08.658 bibi[12436:131119] test.strMutableCopy: 0x1094810a0 str1
2017-06-19 14:24:18.622 bibi[13655:149113] ------------------------------------华丽分割线-------------

2017-06-19 14:24:18.678 bibi[13655:149113] -------------给字符串属性赋值可变字符串-----------------
2017-06-19 14:24:18.679 bibi[13655:149113] ------赋值MuString的log------
2017-06-19 14:24:18.679 bibi[13655:149113] MuString: 0x60800007e580 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strStrong: 0x60800007e580 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strCopy: 0xa004d05041412da8 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strMutableStrong: 0x60800007e580 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strMutableCopy: 0xa004d05041412da8 MuString

2017-06-19 14:24:18.680 bibi[13655:149113] ------- 改变原字符串为MuString_test后log -------
2017-06-19 14:24:18.680 bibi[13655:149113] MuString: 0x60800007e580 MuString_test
2017-06-19 14:24:18.680 bibi[13655:149113] test.strStrong: 0x60800007e580 MuString_test
2017-06-19 14:24:18.680 bibi[13655:149113] test.strCopy: 0xa004d05041412da8 MuString
2017-06-19 14:24:18.680 bibi[13655:149113] test.strMutableStrong: 0x60800007e580 MuString_test
2017-06-19 14:24:18.680 bibi[13655:149113] test.strMutableCopy: 0xa004d05041412da8 MuString

结论
给字符串属性赋值不可变字符串,strong、copy修饰的可变和不可变字符串属性都是指针拷贝;
给字符串属性赋值可变字符串,strong修饰的可变和不可变字符串属性是指针拷贝,而copy修饰的可变和不可变字符串属性都是内容拷贝。

说明:第一种情况,给字符串属性赋值不可变字符串,虽然strong、copy修饰的属性都是指针拷贝,但
     是因为源数据是不可变字符串,导致源数据值改变后,相应的就是另外一个指针地址了,但是这
     些属性还是原来的指针,所以值也是原来的值不会改变;

     第二种情况,给字符串属性赋值可变字符串,strong修饰的属性是指针拷贝,所以源可变字
     符串值改变后,指针没变,则strong修饰的属性指针与源字符串一样,所以值也跟着变化;
     而copy修饰的字符串属性是内容拷贝,源字符串的值改变和属性已经没有关系了,因而不会引起属性值改变。

    所以,我们如果从效果来看的话,想要源字符串值的改变不引起属性字符串值的改变,只有当源字符串
是可变字符串时,属性才需要用copy修饰,其他情况使用strong,copy修饰效果是一样的,虽然是指
针拷贝,但是源字符串值的改变不会引起属性字符串值的改变。当然我们还是要理解他们的区别才是王
道。所以一般字符串属性都是用copy来修饰,这是最靠谱的用法!

二、字符串调用copy、mutableCopy方法给字符串赋值

先看代码

//不可变字符串
NSString *str = @"str";
NSString *str1 = [str copy];       //指针拷贝
NSString *str2 = [str mutableCopy]; //内容拷贝
NSMutableString *str3 = [str copy]; //指针拷贝
NSMutableString *str4 = [str mutableCopy]; //内容拷贝

NSLog(@"指针1:%p, %p, %p, %p, %p", str, str1, str2, str3, str4);
/*
 指针1:0x1041093f0, 0x1041093f0, 0x7f951840b6e0, 0x1041093f0, 0x7f951840dfe0
 */

//可变字符串
NSMutableString *str5 = [NSMutableString stringWithString:@"MuStr"];
str1 = [str5 copy];        //内容拷贝
str2 = [str5 mutableCopy]; //内容拷贝
str3 = [str5 copy];        //内容拷贝
str4 = [str5 mutableCopy]; //内容拷贝

NSLog(@"指针2:%p, %p, %p, %p, %p", str5, str1, str2, str3, str4);
NSLog(@"值2:%@, %@, %@, %@, %@", str5, str1, str2, str3, str4);
/*
 指针2:0x7f9518410af0, 0x7f9518435840, 0x7f9518416390, 0x7f9518403a00, 0x7f951840b6e0
 值2:Mustr, Mustr, Mustr, Mustr, Mustr
 */

[str5 appendString:@"_test"];
NSLog(@"指针3:%p, %p, %p, %p, %p", str5, str1, str2, str3, str4);
NSLog(@"值3:%@, %@, %@, %@, %@", str5, str1, str2, str3, str4);
/*
 指针3:0x7f9518410af0, 0x7f9518435840, 0x7f9518416390, 0x7f9518403a00, 0x7f951840b6e0
 值3:Mustr_test, Mustr, Mustr, Mustr, Mustr
 */
结论:1)、不可变字符串使用copy方法赋值给其他可变或不可变字符串,都是指针拷贝;
     2)、不可变字符串使用mutableCopy方法赋值给可变或不可变字符串,和可变字符串使用copy方法或者mutableCopy方法赋值给其他可变或不可变字符串,都是内容拷贝

给属性字符串赋值

stringTest *test = [[stringTest alloc] init];
NSString *str = @"str1";

//不可变字符串调用copy方法,全部指针拷贝
test.strStrong = [str copy];
test.strCopy = [str copy];
test.strMutableStrong = [str copy];
test.strMutableCopy = [str copy];
NSLog(@"指针1:%p, %p, %p, %p, %p", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针1:%@, %@, %@, %@, %@", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针1:0x101be34f0, 0x101be34f0, 0x101be34f0, 0x101be34f0, 0x101be34f0
//指针1:str1, str1, str1, str1, str1

//不可变字符串调用mutableCopy方法,全部内容拷贝
str = @"str2";
test.strStrong = [str mutableCopy];
test.strCopy = [str mutableCopy];
test.strMutableStrong = [str mutableCopy];
test.strMutableCopy = [str mutableCopy];
NSLog(@"指针2:%p, %p, %p, %p, %p", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针2:%@, %@, %@, %@, %@", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针2:0x101be3510, 0x7ff939498790, 0x7ff9394a2020, 0x7ff9394970c0, 0x7ff939405d40
//指针2:str2, str2, str2, str2, str2

//可变字符串调用copy方法,全部内容拷贝
NSMutableString *str2 = [NSMutableString stringWithString:@"MuStr1"];
test.strStrong = [str2 copy];
test.strCopy = [str2 copy];
test.strMutableStrong = [str2 copy];
test.strMutableCopy = [str2 copy];
NSLog(@"指针3:%p, %p, %p, %p, %p", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针3:%@, %@, %@, %@, %@", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针3:0x7ff93951f540, 0x7ff93954a100, 0x7ff9395288c0, 0x7ff939516ca0, 0x7ff939548db0
//指针3:MuStr1, MuStr1, MuStr1, MuStr1, MuStr1

//可变字符串调用mutableCopy方法,全部内容拷贝
[str2 appendString:@"MuStr2"];
test.strStrong = [str2 mutableCopy];
test.strCopy = [str2 mutableCopy];
test.strMutableStrong = [str2 mutableCopy];
test.strMutableCopy = [str2 mutableCopy];
NSLog(@"指针4:%p, %p, %p, %p, %p", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针4:%@, %@, %@, %@, %@", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针4:0x7ff93951f540, 0x7ff93951f320, 0x7ff93954a100, 0x7ff9395627b0, 0x7ff939516ca0
//指针4:MuStr1MuStr2, MuStr1MuStr2, MuStr1MuStr2, MuStr1MuStr2, MuStr1MuStr2
结论:1)、不可变字符串调用copy给strong, copy修饰的属性赋值,都是指针拷贝;
     2)、不可变字符串调用mutableCopy, 和可变字符串调用copy,和可变字符串调用mutableCopy方法给strong、copy修饰的属性赋值,都是内容拷贝

结论

属性修饰符copy不一定代表着深拷贝,碰上数据源为不可变数据则是浅拷贝(指针拷贝),碰上数据源是可变数据则是深拷贝(内容拷贝);
NSObject的方法copy也不一定代表着浅拷贝,碰上数据源为不可变数据则是浅拷贝,碰上数据源是可变数据则是深拷贝;
NSObject的方法mutableCopy不管数据源是不可变还是可变,都是深拷贝

相关文章

网友评论

      本文标题:iOS字符串深拷贝(内容拷贝),浅拷贝(指针拷贝)以及字符串st

      本文链接:https://www.haomeiwen.com/subject/ulsgqxtx.html