Object-C的淺拷貝與深拷貝區別

一、要了解淺拷貝與深拷貝,首要的是理解淺拷貝是什麼深拷貝是什麼數組

<1>淺拷貝:就至關於retain,只copy了一個對象的引用,和自己是同一個對象,就至關於影子。atom

<2>深拷貝:重新開闢了一塊內存空間,用來存放原來對象裏面的東西,這個時候,copy出來的對象和原來的對象不是同一個對象,他們的內容同樣,就至關於克隆人。spa

<3>拷貝出來的的對象是什麼類型取決於使用什麼拷貝。3d

 

二、拷貝的用法code

<1>不可變copy拷貝不可變對象(淺拷貝):對象

NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil];
NSArray *array1=[array copy];
NSLog(@"array1=%@",array1);
NSLog(@"array=%p,array1=%p",array,array1);
NSLog(@"array = %lu ,array1 = %lu",[array retainCount],[array1 retainCount]);

 

其輸出結果:blog

看輸出結果反饋出:對不可變數組array進行不可變copy時,拷貝出來的array1是跟array同樣的對象且兩個數組的引用計數都+1,至關於對array自己的一個引用而已。內存

 

 

<2>不可變copy拷貝可變對象(深拷貝):it

NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil];
NSArray *array=[mArray copy];
NSLog(@"mArray=%p,array=%p",mArray,array);
NSLog(@"array=%@",array);
NSLog(@"array的類型%@",[array class]);
NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其輸出結果:io

看輸出結果反饋出:對可變數組mArray進行不可變copy操做,拷貝出來的array數組與mArray數組的內存地址是不同的且兩塊內存地址內容是相同的,而內容是同樣的且引用計數不發生改變,array數組的類型不變依舊是不可變數組。由此能夠得出不可變copy拷貝可變對象是深拷貝。

 

 

<3>可變copy拷貝不可變對象(深拷貝):

NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil];
NSMutableArray *mArray=[array mutableCopy];
NSLog(@"-%@",[[array mutableCopy] class]);
NSLog(@"array=%p,mArray=%p",array,mArray);
NSLog(@"mArray=%@",mArray);
NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其輸出結果:

看輸出結果反饋出:對不可變數組array進行可變可變copy操做,拷貝出來的mArray數組與array數組的內存地址不一樣且兩塊內存地址內容是相同的,且拷貝出來的對象是可變的,引用計數並無發生改變,由此能夠得出可變copy拷貝不可變對象是深拷貝。

 

 

<4>可變copy拷貝可變對象(深拷貝):

 NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil];
 NSMutableArray *array=[mArray mutableCopy];
 NSLog(@"%@",[[mArray mutableCopy] class]);
 NSLog(@"mArray=%p,array=%p",mArray,array);
 NSLog(@"array=%@",array);
 NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其輸出結果:

看輸出結果反饋出:對可變數組array進行可變可變copy操做,拷貝出來的array數組與mArray數組的內存地址不一樣且兩塊內存地址內容是相同的,且拷貝出來的對象是可變的,沒有引發引用計數的變化,由此能夠得出可變copy拷貝可變對象是深拷貝。

 

 

<5>自定義類的copy:

自定義一個person類

.h文件

#import <Foundation/Foundation.h>
//要實現copy必須遵照NSCopying或者NSMutableCopying協議,這裏面有一個必須實現的協議copyWithZone:
@interface Person : NSObject<NSCopying>
@property(retain,nonatomic)NSString *name;

@property(copy,nonatomic)NSArray *array;
@property(copy,nonatomic)NSMutableArray *mArray;

@end

 

.m文件

#import "Person.h"

@implementation Person
-(id)copyWithZone:(NSZone *)zone
{
    Person *pp=[[Person alloc]init];
//    NSLog(@"pp=%p",pp);
    pp.name=self.name;
    return pp;
}
@end

 

在main.m文件中,導入person類頭文件且添加下列代碼

/*
     要實現copy必須遵照NSCopying或者NSMutableCopying協議,這裏面有一個必須實現的協議copyWithZone:
*/

    Person *p=[[Person alloc]init];
    p.name=@"張三";
    Person *p1=[p copy];
    NSLog(@"p=%p,p1=%p",p,p1);
    NSLog(@"p1的名字爲%@",p1.name);

運行結果獲得:

能夠得出:自定義對象進行copy操做獲得的是兩塊補同樣的內存地址,且內容是同樣的。

 

 

<6>屬性的copy:

    1copy修飾不可變屬性的時候,就至關於retain

    2copy修飾可變屬性的時候,至關於不可變copy拷貝可變對象。屬於深拷貝,這個時候,屬性和對屬性賦值的對象的內存都須要單獨管理

    3、建議對象類型都是用retain

相關文章
相關標籤/搜索