copy和mutableCopy 淺拷貝和深拷貝

首先來看copy和MutableCopy的實現過程。
一個對象要實現copy,首先要繼承NSCopying的協議,然后實現 + (id)copyWithZone:(struct _NSZone * )zone
同理,一個對象要實現mutableCopy,首先要繼承NSMutableCopying的協議,然后實現+ (id)mutableCopyWithZone:(struct _NSZone * )zone

  • copy只會產生不可變副本對象
  • mutableCopy只會產生可變副本對象

再來看看容器類對象的概念:主要有NSArray、NSSet和NSDictionary,以及他們的Mutable子類。非容器對象的主要有NSString、NSNumber等。


然后分情況討論一下copy 和 mutableCopy是深拷貝還是淺拷貝。

  • 對非容器對象,對不可變對象拷貝,copy為淺拷貝,mutableCopy是深拷貝
NSString * original = @"original";
NSString * string1 = [original copy];
NSMutableString * string2 = [original mutableCopy];
NSLog(@"%@ %p",original,original);
NSLog(@"%@ %p",string1,string1);
NSLog(@"%@ %p",string2,string2);

這里可以看出來original 和string1 的地址一樣 ,original 和string2地址不一樣。

  • 對非容器對象,對可變對象拷貝,copy和mutableCopy都是深拷貝,但是copy返回的對象不可變
NSMutableString * original = [NSMutableString stringWithString:@"original"];
NSString * string1 = [original copy];
NSMutableString * string2 = [original mutableCopy];
NSMutableString * string3 = [original copy];
NSLog(@"%@ %p",original,original);
NSLog(@"%@ %p",string1,string1);
NSLog(@"%@ %p",string2,string2);
NSLog(@"%@ %p",string3,string3);
    //error copy的是不可變對象 不能執行appendString方法
//    [string3 appendString:@"add"];

original 和string1、 string2、string3的地址都不一樣,但是string3 返回的是不可變類型,不能執行appendString方法

  • 對容器對象,對不可變對象拷貝,copy為淺拷貝,mutableCopy是深拷貝
    NSArray * original = @[@"a",@"b",@"c"];
    NSArray * array1 = [original copy];
    NSMutableArray * array2 = [original mutableCopy];
    NSLog(@"%@ %p",original,original);
    NSLog(@"%@ %p",array1,array1);
    NSLog(@"%@ %p",array2,array2);

以上結論對容器對象仍然適用。 original和array1的地址是一樣的,original和array2不一樣。

  • 對容器對象,對可變對象拷貝,copy和mutableCopy都是深拷貝,但是copy返回的對象不可變
    NSMutableArray * original = [NSMutableArray arrayWithArray:   @[@"a",@"b",@"c"]];
    
    NSArray * array1 = [original copy];
    NSMutableArray * array2 = [original mutableCopy];
    NSMutableArray * array3 = [original copy];
    
    NSLog(@"%@ %p",original,original);
    NSLog(@"%@ %p",array1,array1);
    NSLog(@"%@ %p",array2,array2);
    NSLog(@"%@ %p",array3,array3);
    
    //    [array3 addObject:@"d"];

以上結論對容器對象仍然適用。 original和array1、array2、array3不一樣。array3返回的是不可變類型 addObject不可執行。

  • 對容器對象,copy和MutableCopy的深拷貝,是拷貝對象本身array,array集合內部的元素還是指針拷貝。
    NSArray * origin = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
    NSArray * array1 = [origin copy];
    NSMutableArray * array2 = [origin mutableCopy];
    
    NSMutableString * string = [origin objectAtIndex:0];
    [string appendString:@"add"];
    
    NSLog(@"%@",origin);
    NSLog(@"%@",array1);
    NSLog(@"%@",array2);

origin、array1、array2都變成了 @[@"aadd",@"b",@"c"]

** 綜上,對于不可變對象的copy是淺拷貝,mutableCopy是深拷貝。對于可變對象,copy和mutableCopy都是深拷貝。對于容器類的copy和mutableCopy,深拷貝的是本身的對象,而對象里面的元素還是是指針拷貝,對于這種蘋果有種叫法是單層深復制。**

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容