iOS中的深復制與淺復制

utgy0944 8年前發布 | 10K 次閱讀 iOS開發 移動開發

很多語言中都有深復制淺復制的概念,如C++,ObjC等。簡單來說,淺復制就是兩個變量指向了同一塊內存區域,深復制就是兩個變量指向了不同的內存區域,但是兩個內存區域里面的內容是一樣的。

淺復制示意圖:

深復制示意圖:

iOS開發中,淺復制和深復制要更復雜一些,涉及到集合對象和非集合對象的copy與mutableCopy。

非集合對象:如NSString,NSInteger,NSNumber……

集合對象:如NSArray,NSDictionary,……

1:非集合對象的copy與mutableCopy。

非集合對象的copy與mutableCopy,只需要遵循以下規則即可:

(1)可變對象的copy和mutableCopy方法都是深復制

(2)不可變對象的copy方法是淺復制,mutableCopy方法是深復制

(3)copy方法返回的對象是不可變對象

下面通過代碼來驗證:

可變對象的copy與 mutableCopy方法:

void testMutable()
{
    //可變對象的復制,copy和mutableCopy都是深拷貝
    NSMutableString *str1 = [NSMutableString stringWithString:@"test"];
    NSMutableString *str2 = [str1 copy];
    //copy返回的是不可變對象,因此str2不能改變,會發生崩潰
    //[str2 appendString:@"test"];
    NSMutableString *str3 = [str1 mutableCopy];
    [str3 appendString:@"test"];
    NSLog(@"%@ %@ %@",str1,str2,str3);
    NSLog(@"%p %p %p",str1,str2,str3);
}

執行結果:

可以看到,三個字符串的地址是不相同的,說明copy和 mutableCopy方法都是深復制。

不可變對象的copy與mutableCopy方法:

void testNoMutable()
{
    NSString *str1 = @"test";
    //直接copy是淺復制
    NSMutableString *str2 = [str1 copy];
    //copy返回的是不可變對象,str2不能被修改,因此會發生崩潰
    //[str2 appendString:@"test"];
    //mutableCopy是深復制
    NSMutableString *str3 = [str1 mutableCopy];
    [str3 appendString:@"test"];
    NSLog(@"%@ %@ %@",str1,str2,str3);
    NSLog(@"%p %p %p",str1,str2,str3);
}

執行結果:

可以看到:前兩個地址一樣,第三個地址不一樣,因此不可變對象的copy方法是淺復制,mutableCopy方法是深復制。

另外需要注意: 無論是可變對象還是不可變對象,copy 方法返回的對象都是不可變的。

2:集合對象的copy與mutableCopy

實際上,集合對象與非集合對象所遵循的規則基本上是一樣的。

可變對象的的copy與mutableCopy 方法

驗證代碼:

void testSetMutable()
{
    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
    //可變對象copy是深復制
    NSMutableArray *array2 = [array1 copy];
    //copy返回的是不可變對象,array2不能被修改,因此會崩潰
    //[array2 addObject:@"d"];
    //可變對象的mutableCopy是深復制
    NSMutableArray *array3 = [array1 mutableCopy];
    [array3 addObject:@"d"];
    NSLog(@"%p %p %p",array1,array2,array3);
}

執行結果:

可以看到地址是不一樣的。說明可變對象的copy和mutableCopy方法都是深復制。

不可變對象的copy與mutableCopy方法

驗證代碼:

void testSetNoMutable()
{
    NSArray *array1 = @[@"a",@"b",@"c"];
    //不可變對象的copy方法,淺復制
    NSArray *array2 = [array1 copy];
    //不可變對象的mutableCopy方法,深復制
    NSArray *array3 = [array1 mutableCopy];
    NSLog(@"%p %p %p",array1,array2,array3);
}

執行結果:

可以看到,前兩個地址一樣,第三個地址不一樣。說明不可變對象的copy方法是淺復制,mutableCopy方法是深復制。

集合對象和非集合對象的一個差別:

上面說的集合對象的深復制并不是嚴格意義上的深復制,而是單層深復制。

單層深復制:對集合對象來說,深復制時只是將第一層對象進行了深復制,內部的對象仍然是淺復制。比如說

NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];

調用copy方法   NSArray *array2 = [array1 copy] ,有分配了一塊內存,array2指向了這塊內存,但是數組內部的元素,指向的仍然是數組1內部的元素,即內部元素是淺復制。

驗證代碼:

void testSetMutable()
{
    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
    //可變對象copy是深復制
    NSMutableArray *array2 = [array1 copy];
    //copy返回的是不可變對象,array2不能被修改,因此會崩潰
    //[array2 addObject:@"d"];
    //可變對象的mutableCopy是深復制
    NSMutableArray *array3 = [array1 mutableCopy];
    [array3 addObject:@"d"];
    NSLog(@"%p %p %p",array1,array2,array3);
    NSLog(@"%p %p %p",array1[0],array2[0],array3[0]);
}

執行結果:

可以看到,三個數組的第一個元素的地址是一樣的,也就是說內部元素是淺復制。

3:集合對象的完全復制

集合對象的完全復制,就是集合中的每一層的元素都是深復制。

方法一:

使用 initWith***: copyItems:YES  方法。

代碼:

void testFullCopy()
{
    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
    NSArray *array2 = [[NSArray alloc] initWithArray:array1 copyItems:YES];
    NSLog(@"%p %p",array1,array2);
    NSLog(@"%p %p",array1[0],array2[0]);
}

執行結果:

可以看到數組元素的地址不一樣。

方法二:

先將集合進行歸檔,然后再解檔。代碼如下:

void testFullCopy2()
{
    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c", nil];
    NSArray *array2 = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array1 ] error:nil];
    NSLog(@"%p %p",array1,array2);
    NSLog(@"%p %p",array1[0],array2[0]);
}

執行結果:

可以看到數組元素的地址不一樣。

來自: http://www.cnblogs.com/acBool/p/5146639.html

 本文由用戶 utgy0944 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!