copy和mutableCopy到底是浅拷贝还是深拷贝?

时间:2021-05-02 19:50:54

请尊重原作者的辛苦劳动,转载请注明出处。http://blog.csdn.net/jslsblog/article/details/38563009


实践是检验真理的唯一标准。下面就让我们在实践中认识copy和mutableCopy的共同点和区别。

1.copy和mutableCopy的实现过程。

想要一个对象能实现copy首先要继承NSCopying的协议,然后实现+ (id)copyWithZone:(struct _NSZone *)zone,mutableCopy对应的是NSMutableCopying协议和+ (id)mutableCopyWithZone:(struct _NSZone *)zone方法。
不同的对象,在实现copyWithZone:和mutableCopyWithZone:的时候实现方式是不同的,这就导致了不同的对象在调用了copy或者mutableCopy后有的是返回原来的指针,有的是返回一个新的指针。



2.NSString copy举例

eg1:常量

NSString *str1 = @"eg";
NSString *str2 = [str1 copy];
这时候打印retainCount,结果str1和str2的都是-1,说明对于字符串常量没有进行计数,copy的时候没有任何效果,结果等同于NSString *str2 = str1;
同理:NSString *str1 = [[NSString alloc] initWithString:@"12345"];
str1的retainCount = -1;说明这样创建也是常量,alloc没有分配内存。



eg2:不可变变量

NSString *str1 = [NSString stringWithFormat:@"eg"];
NSLog(@"str1 retainCount:%d",(int)[str1 retainCount]);
NSString *str2 = [str1 copy];
NSLog(@"str1 retainCount:%d",(int)[str1 retainCount]);
NSLog(@"str2 retainCount:%d",(int)[str2 retainCount]);


打印的结果是
str1 retainCount:1
str1 retainCount:2
str2 retainCount:2
而且你如果打印str1和str2的地址,你会发现两者的地址也是不同的,并且地址相差的长度为8.当[str1 release]的时候str1和str2的retainCount都变为1.从以上结果可以推测str1和str2指向同一个对象,享有相同的计数值。这时候的copy = retain。


eg3:可变变量

    NSMutableString *str1 = [NSMutableString stringWithFormat:@"ss"];
    NSLog(@"str1 retainCount:%d",(int)[str1 retainCount]);
    NSString *str2 = [str1 mutableCopy];//或者使用 NSString *str2 = [str1 copy];

    NSLog(@"str1 retainCount:%d",(int)[str1 retainCount]);
    NSLog(@"str2 retainCount:%d",(int)[str2 retainCount]);

    打印结果:
    str1 retainCount:1
str1 retainCount:1
str2 retainCount:1
如果[str1 release];是不会影响str2的值和retainCount。从以上结果可以推断出copy 和mutableCopy等于从新创建一个新的NSString,并且把str1的值付给str2,str1和str2是完全不同的两个对象。


3.总结

从以上三个例子说明了不同的对象在不同的情况下对copyWithZone:和mutableCopyWithZone:的实现是不同的,不能一概而论。
浅拷贝就是复制一份指针,而深拷贝就是创建一个新的对象,然后把值复制过去,原来的对象和新建的对象之后没有任何关系。copy和mutableCopy不能一概的说是浅拷贝还是深拷贝,需要针对不同的实现方法来判断。

和NSString类似的类还有NSNumber. NSArray和 NSString略有不同。NSArray不论用什么方式创建都会retainCount=1,mutableCopy和copy都会创建新的数组。