实例浅析oc中的浅复制和深复制的本质
代码段1:
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:@"one",@"two",@"three",@"four", nil];
NSMutableArray *dataArray2;
// copy
dataArray2 = dataArray;
[dataArray2 removeObjectAtIndex:0];
NSLog(@"dataArray:");
for (NSString *elem in dataArray) {
NSLog(@"%@",elem);
}
NSLog(@"dataArray2: ");
for (NSString *elem in dataArray2) {
NSLog(@"%@",elem);
}
// mutableCopy
dataArray2 = [dataArray mutableCopy];
[dataArray2 removeObjectAtIndex:0];
NSLog(@"dataArray:");
for (NSString *elem in dataArray) {
NSLog(@"%@",elem);
}
NSLog(@"dataArray2: ");
for (NSString *elem in dataArray2) {
NSLog(@"%@",elem);
}
}
return 0;
}
打印结果如下:
dataArray:
two
three
four
dataArray2:
two
three
four
dataArray:
two
three
four
dataArray2:
three
four
代码段2:
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"1"],
[NSMutableString stringWithString:@"2"],
[NSMutableString stringWithString:@"3"],
[NSMutableString stringWithString:@"4"],
[NSMutableString stringWithString:@"5"],
[NSMutableString stringWithString:@"6"],
[NSMutableString stringWithString:@"7"],
nil];
NSMutableArray *dataArray2;
NSMutableString *mStr;
NSLog(@"dataArray :");
for (NSString *elem in dataArray) {
NSLog(@"%@",elem);
}
// 做一次拷贝,然后改变第一个字符串
dataArray2 = [dataArray mutableCopy];
mStr = [dataArray objectAtIndex:0];
[mStr appendString:@"oc"];
NSLog(@"dataArray :");
for (NSString *elem in dataArray) {
NSLog(@"%@",elem);
}
NSLog(@"dataArray2 :");
for (NSString *elem in dataArray2) {
NSLog(@"%@",elem);
}
}
return 0;
}
打印结果如下:
dataArray :
1
2
3
4
5
6
7
dataArray :
1oc
2
3
4
5
6
7
dataArray2 :
1oc
2
3
4
5
6
7
为了便于理解,我们可以把数组对象看成指针数组,dataArray这个指针是指向指针数组的指针,数组中的元素指针指向的是对象
分析:copy复制对象结果是dataArray和dataArray2指向同一个数组对象。
MutableCopy复制对象的结果是,创建数组对象的副本,即dataArray 和 dataArray2指向不同的对象,但是两个数组对象中的元素对应的指向的同一个对象 即dataArray[0] 和 dataArray[0]指向同一个对象,dataArray[1] 和 dataArray2[1]指向同一个对象
从内存的管理的角度去分析
copy的结果是数组对象的计数器加1,mutableCopy的结果是数组对象中的元素(对象)的计数器加1
代码段1:分析
copy只是复制数据对象的引用,数组对象本身发生改变,不管用哪个指针去访问,结果都相同
MutableCopy复制元素的引用,因为两个数据对象指针并没有指向同一个数组对象,所以dataArray2数组元素的个数改变并不影响dataArray
dataArray的元素依旧有指针指向@“two”这个字符串对象
代码段2:分析
mutableCopy创建了数据对象的副本,并把副本的地址传递给dataArray2。数组对象的元素对象计数器都加1。当我们改变了数组元素对象的内容的时候,由于两个数组对象的元素指针指向相同的对象,所以两个数组对象打印结果会相同
想要做到完全复制,我们就要一层一层的胃对象创建副本,知道最底层,这个怎么理解呢,就拿上面两段代码来说copy没有创建副本,mutableCopy创建了一层,我们只要再为数组对象元素,为这些字符串对象都创建副本,那我我们再怎么去改动dataArray 也不会影响到dataArray2
我们可以使用Foundation的归档能力创建对象的深复制。如下代码所示,dataArray归档到一个缓冲区,然后再把它解归档,将结果指派给dataArray2,从而将dataArray复制给dataArray。这个过程不需要使用文件。归档和解归档过程都可以在内存中发生。代码如下
#import
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSData *data;
NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"1"],
[NSMutableString stringWithString:@"2"],
[NSMutableString stringWithString:@"3"],
[NSMutableString stringWithString:@"4"],
[NSMutableString stringWithString:@"5"],
[NSMutableString stringWithString:@"6"],
[NSMutableString stringWithString:@"7"],
nil];
NSMutableArray *dataArray2;
NSMutableString *mStr;
// 用archiver进行深复制
data = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
mStr = [dataArray2 objectAtIndex:1];
[mStr appendString:@"ios"];
NSLog(@"dataArray :");
for (id obj in dataArray) {
NSLog(@"%@",obj);
}
NSLog(@"dataArray2 :");
for (id obj in dataArray2) {
NSLog(@"%@",obj);
}
}
return 0;
}
dataArray :
1
2
3
4
5
6
7
dataArray2 :
1
2ios
3
4
5
6
7