關(guān)于Copy的深入解析

一直對(duì)字符串為什么要使用copy修飾?使用strong修飾又有什么區(qū)別?這些問(wèn)題一直還存在著一些疑惑。下面就通過(guò)代碼來(lái)研究哈。

字符串為什么要使用copy?

首先我們定義一個(gè)copy修飾的字符串屬性,一個(gè)strong類型的字符串

/// strong修飾字符串

@property (nonatomic,strong) NSString *name_strong;

/// copy修飾字符串

@property (nonatomic,copy) NSString *name_copy;

ARC下字符串的copy修飾的字符串set方法的結(jié)構(gòu)

- (void)setName_copy:(NSString *)name_copy

{

_name_copy = [name_copy copy];

}

ARC下strong修飾的字符串的set 方法的結(jié)構(gòu)

- (void)setName_strong:(NSString *)name_strong

{

_name_strong = name_strong;

}

測(cè)試的代碼

- (void)test1

{

NSMutableString *stringM = [NSMutableString stringWithFormat:@"hello"];

self.name_copy = stringM;

self.name_strong = stringM;

[stringM appendString:@" world"];

NSLog(@"name_copy=%@",self.name_copy);

NSLog(@"name_strong=%@",self.name_strong);

}

控制臺(tái)打印結(jié)果:

2016-08-17 21:24:35.449 Copy演練[1633:181999] name_copy=hello

2016-08-17 21:24:35.450 Copy演練[1633:181999] name_strong=hello world

從打印的結(jié)果中我們可以得出結(jié)論:

假如有一個(gè)NSMutableString,現(xiàn)在用他給一個(gè)strong(retain)修飾的NSString賦值,那么只是將NSString指向了NSMutableString所指向的位置,并對(duì)NSMUtbaleString計(jì)數(shù)器加1,此時(shí),如果對(duì)NSMutableString進(jìn)行修改,也會(huì)導(dǎo)致NSString的值修改,原則上這是不允許的,所以字符串需要使用copy 來(lái)修飾,這樣在對(duì)NSMutableString進(jìn)行修改的時(shí)候,不會(huì)影響NSString的值。

深拷貝與淺拷貝

不可變字符串的拷貝

先上示例代碼:

NSString *string = @"hello";

NSLog(@"string=%p",string);

// 淺拷貝

NSString *stringCopy = [string copy];

NSLog(@"stringCopy=%p",stringCopy);

// 深拷貝

NSMutableString *stringMCopy = [string mutableCopy];

NSLog(@"stringMCopy=%p",stringMCopy);

// 測(cè)試深拷貝是否成功

[stringMCopy appendString:@"world"];

NSLog(@"%@ = %p",stringMCopy,stringMCopy);

控制臺(tái)輸出結(jié)果

2016-08-17 21:41:37.597 Copy演練[1657:190183] string=0x104e611d0

2016-08-17 21:41:37.598 Copy演練[1657:190183] stringCopy=0x104e611d0

2016-08-17 21:41:37.598 Copy演練[1657:190183] stringMCopy=0x7ff7d069f880

2016-08-17 21:41:37.598 Copy演練[1657:190183] helloworld = 0x7ff7d069f880

從上面結(jié)果中可以看出來(lái),使用[string copy]拷貝的字符串的地址和string是一樣的,說(shuō)明淺拷貝拷貝的是指針,地址并沒(méi)有發(fā)生改變。[string mutableCopy]拷貝的字符串和string的地址不一樣,說(shuō)明深拷貝拷貝的是地址,并且從數(shù)據(jù)結(jié)果中可以看到[string mutableCopy]拷貝對(duì)象能夠拼接字符串,說(shuō)明對(duì)象也是跟著發(fā)生了改變由不可變變?yōu)榭勺冏址?/p>

也可以得出結(jié)論: copy返回不可變對(duì)象,mutablecopy返回可變對(duì)象

可變字符串的拷貝

示例代碼:

// 可變字符串

NSMutableString *stringM = [NSMutableString stringWithString:@"hello"];

NSLog(@"stringM=%p",stringM);

// 深拷貝 : 本質(zhì)把可變的拷貝成了不可變的

NSString *stringCopy = [stringM copy];

NSLog(@"stringCopy=%p",stringCopy);

// 深拷貝 : 本質(zhì)把可變的拷貝成了不可變的

//? ? NSMutableString *stringMCopy = [stringM copy];

//? ? NSLog(@"stringMCopy=%p",stringMCopy);

// 測(cè)試深拷貝和淺拷貝? 運(yùn)行以后報(bào)錯(cuò),不可以給不可變的對(duì)象追加字符串

//? ? [stringMCopy appendString:@"world"];

//? ? NSLog(@"%@",stringMCopy);

// 深拷貝 : 拷貝出一個(gè)新的可變字符串

NSMutableString *stringMCopy = [stringM mutableCopy];

NSLog(@"stringMCopy=%p",stringMCopy);

// 測(cè)試深拷貝和淺拷貝

[stringMCopy appendString:@"world"];

NSLog(@"%@",stringMCopy);

控制臺(tái)打印結(jié)果:

2016-08-17 22:02:48.658 Copy演練[1711:202680] stringM=0x7fc440c16750

2016-08-17 22:02:48.659 Copy演練[1711:202680] stringCopy=0xa00006f6c6c65685

2016-08-17 22:02:48.659 Copy演練[1711:202680] stringMCopy=0x7fc440f17170

2016-08-17 22:02:48.659 Copy演練[1711:202680] helloworld

從控制中我們可以看出NSMutableString類型的字符串在[stringM copy]后地址發(fā)生了改變,NSMutableString類型的字符串在[stringM mutableCopy]后地址也發(fā)生了改變。

不可變集合的拷貝

示例代碼:

NSArray *array = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];

NSLog(@"array=%@ %p",[array class],array);

NSArray *arrayCopy = [array copy];

NSLog(@"arrayCopy=%@ %p",[arrayCopy class],arrayCopy);

NSMutableArray *arrayMCopy = [array mutableCopy];

NSLog(@"arrayMCopy=%@ %p",[arrayMCopy class],arrayMCopy);

[arrayMCopy addObject:@"d"];

[arrayMCopy removeObjectAtIndex:0];

輸出結(jié)果:

2016-08-17 22:20:00.950 Copy演練[1783:214373] array=__NSArrayI 0x7fddc1e19720

2016-08-17 22:20:00.951 Copy演練[1783:214373] arrayCopy=__NSArrayI 0x7fddc1e19720

2016-08-17 22:20:00.951 Copy演練[1783:214373] arrayMCopy=__NSArrayM 0x7fddc1d14910

從上面的代碼中得出結(jié)論:

1.arrayCopy是和array同一個(gè)NSArray對(duì)象(指向相同的對(duì)象,包括array里面的元素也是指向相同的指針).

2.arrayMCopy是array的可變副本,指向的對(duì)象和array不同,但是其中的元素和array中的元素指向的是同一個(gè)對(duì)象.arrayMCopy還可以修改自己的對(duì)象.

3.array和arrayCopy是指針復(fù)制,而arrayMCopy是對(duì)象復(fù)制,arrayMCopy還可以改變期內(nèi)的元素 : 刪除或添加.但是注意的是,容器內(nèi)的元素內(nèi)容都是指針復(fù)制.

可變集合的拷貝

示例代碼:

// 不可變數(shù)組元素中有個(gè)可變字符串

NSMutableString *stringM = [NSMutableString stringWithString:@"a"];

NSLog(@"stringM=%p",stringM);

NSArray *array = [NSArray arrayWithObjects:stringM,@"b",@"c",nil];

NSLog(@"array=%@ %p",[array class],array);

// 淺拷貝

NSArray *arrayCopy = [array copy];

NSLog(@"arrayCopy=%@ %p",[arrayCopy class],arrayCopy);

// 深拷貝

NSMutableArray *arrayMCopy = [array mutableCopy];

NSLog(@"arrayMCopy=%@ %p",[arrayMCopy class],arrayMCopy);

// 測(cè)試數(shù)組里面的元素是指針拷貝

NSMutableString *testString = [arrayMCopy objectAtIndex:0];

NSLog(@"testString=%@ %p",testString,testString);

// 演示集合元素的指針拷貝的效果

[testString appendString:@"tail"];

NSMutableString *testString1 = [arrayMCopy objectAtIndex:0];

NSLog(@"testString1=%@ %p",testString1,testString1);

輸出結(jié)果:

2016-08-17 22:25:39.600 Copy演練[1805:217531] stringM=0x7fc95ae08240

2016-08-17 22:25:39.601 Copy演練[1805:217531] array=__NSArrayI 0x7fc95ad87e50

2016-08-17 22:25:39.601 Copy演練[1805:217531] arrayCopy=__NSArrayI 0x7fc95ad87e50

2016-08-17 22:25:39.601 Copy演練[1805:217531] arrayMCopy=__NSArrayM 0x7fc95ad25270

2016-08-17 22:25:39.601 Copy演練[1805:217531] testString=a 0x7fc95ae08240

2016-08-17 22:25:39.601 Copy演練[1805:217531] testString1=atail 0x7fc95ae08240

得出結(jié)論:

可變字符串在數(shù)據(jù)進(jìn)行深拷貝還是淺拷貝后地址依然不變,充分說(shuō)明容器內(nèi)的元素都是指針拷貝

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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