細(xì)說(shuō)iOS之淺拷貝深拷貝

對(duì)于iOS中淺拷貝和淺拷貝,大家只是模糊的知道前者是復(fù)制了一份對(duì)象的地址,也就是同一個(gè)對(duì)象增加了一個(gè)指向它的指針,而后者是一個(gè)新的指針變量指向一個(gè)新的對(duì)象,這個(gè)新的對(duì)象是原對(duì)象的復(fù)制品,即對(duì)象屬性完全相同只是位于不同的內(nèi)存空間。但針對(duì)數(shù)組類(lèi)型的對(duì)象時(shí)還需要更仔細(xì)理解一下。

數(shù)組類(lèi)型的淺拷貝同樣是開(kāi)辟一個(gè)新的指針指向該數(shù)組,兩個(gè)指針操作的是同一個(gè)數(shù)組;而深拷貝分為兩種情況,一是拷貝數(shù)組中的對(duì)象地址至一個(gè)新的數(shù)組,新數(shù)組中對(duì)象和原數(shù)組中對(duì)象是相同的內(nèi)存地址即相同的實(shí)例,二是拷貝數(shù)組中的對(duì)象至一個(gè)新的數(shù)組,新數(shù)組中對(duì)象和原數(shù)組中對(duì)象是不同的實(shí)例。

還是直接用代碼輸出拷貝的數(shù)組地址來(lái)解釋吧。

首先創(chuàng)建數(shù)組arrayA,其中添加了兩個(gè)對(duì)象person1和person2,并且輸出arrayA的地址如圖1所示。

NSMutableArray *arrayA = [[NSMutableArray alloc]initWithCapacity:0];

Person *person1 = [[Person alloc]initWithHeight:180 withAge:18 withName:@"Joe"];

Person *person2 = [[Person alloc]initWithHeight:150 withAge:15 withName:@"Kate"];

[arrayA addObject:person1];

[arrayA addObject:person2];

NSLog(@"arrayA:%p,%@",arrayA,arrayA);

1.原數(shù)組arrayA的內(nèi)存地址和所含對(duì)象的內(nèi)存地址

然后創(chuàng)建arrayB數(shù)組,用來(lái)拷貝arrayA,并且向arrayB中添加對(duì)象person3,輸出arrayB和arrayA的地址如圖2所示,兩個(gè)數(shù)組完全一致,arrayB其實(shí)就是arrayA的淺拷貝。

NSMutableArray *arrayB = arrayA;

Person *person3 = [[Person alloc]initWithHeight:170 withAge:23 withName:@"Mike"];

[arrayB addObject:person3];

NSLog(@"arrayB:%p,%@",arrayB,arrayB);

NSLog(@"arrayA:%p,%@",arrayA,arrayA);

2.淺拷貝之a(chǎn)rrayB和arrayA的內(nèi)存地址

創(chuàng)建數(shù)組arrayA的備份數(shù)組arrayC,并且向arrayC中添加對(duì)象person4,輸出arrayC的內(nèi)存地址和數(shù)組中對(duì)象的地址如圖3,可以發(fā)現(xiàn)arrayC和arrayA的地址不同,但是其中的對(duì)象地址卻相同,也就是說(shuō)arrayC數(shù)組中的對(duì)象和arrayA數(shù)組中對(duì)象是同一份,指向相同的內(nèi)存地址。當(dāng)對(duì)數(shù)組arrayA中的person1操作,那么數(shù)組arrayC中的person1也會(huì)相應(yīng)的變化。

NSMutableArray *arrayC = [[NSMutableArray alloc]initWithArray:arrayA];

Person *person4 = [[Person alloc]initWithHeight:175 withAge:24 withName:@"趙子龍"];

[arrayC addObject:person4];

NSLog(@"arrayC:%p,%@",arrayC,arrayC);

3.深拷貝arrayC的內(nèi)存地址和數(shù)組中對(duì)象地址

有時(shí)候,我們想兩份數(shù)組分別操作時(shí)而互不影響其中的對(duì)象,也就是兩個(gè)數(shù)組位于不同的內(nèi)存地址,并且所含的對(duì)象屬性完全相同但并不是同一個(gè)實(shí)例,那么就需要在深拷貝數(shù)組的同時(shí)深拷貝數(shù)組中的對(duì)象。代碼如下,創(chuàng)建arrayD的同時(shí)拷貝arrayA中的所有對(duì)象,并且向arrayD中添加對(duì)象person5,輸出arrayD的內(nèi)存地址和所含對(duì)象的地址如圖4所示。

NSMutableArray *arrayD = [[NSMutableArray alloc]initWithArray:arrayA copyItems:YES];

Person *person5 = [[Person alloc]initWithHeight:177 withAge:44 withName:@"趙云"];

[arrayD addObject:person5];

NSLog(@"arrayD:%p,%@",arrayD,arrayD);

4.arrayD的內(nèi)存地址和所含對(duì)象的內(nèi)存地址

arrayD的內(nèi)存地址arrayA的內(nèi)存地址不同,而且所含對(duì)象的地址也是不同的,這樣在操作arrayD和arrayA的時(shí)候,兩者是互不影響的。

備注,NSMutableArray *arrayD = [[NSMutableArray alloc]initWithArray:arrayA copyItems:YES];這句代碼的使用需要數(shù)組中的對(duì)象遵循NSCoping和NSMutableCopying協(xié)議,也就是這里的Person類(lèi)重載如下的兩個(gè)方法,否則直接用上面的API會(huì)崩潰。

-(id)copyWithZone:(NSZone *)zone;

-(id)mutableCopyWithZone:(NSZone *)zone;

重載代碼的示例如下:

-(id)copyWithZone:(NSZone *)zone

{

Person *A = [[self class] allocWithZone:zone];

A.age = self.age;

A.height = self.height;

A.name = self.name;

return A;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容