copy,retain,strong的區別
之前的編碼中,對於NSString的property修飾,習慣性使用copy,只是粗略的知道copy屬於深複製,retain/strong屬於淺複製,並沒有對其深究。最近需要詳細瞭解這一塊知識,在網上搜索相關內容,並且用程式碼驗證,檢視對比了記憶體地址,做一些總結。
一、之前對於copy和retain/strong的區別理解是這樣的:
copy是複製了源物件所在記憶體空間的資料,放入目的物件指標指向的記憶體空間,並且令目的物件引用計數為1,對於源物件的引用計數沒有影響;源物件內容的改變不會影響到目的物件。
retain/strong是目的物件指標指向源物件的記憶體空間,源物件的引用計數+1;源物件的改變會影響到目的物件。
mutablecopy返回的是可變的物件,copy返回的是不可變的物件。
二、程式碼驗證探究
1、源物件為不可變 NSString
- NSString*str = @"test";
- NSString* retainStr = [str retain];
- NSString* copyStr = [str copy];
- NSMutableString* mcopyStr = [str mutableCopy];
- NSLog(@"str addr = %p",str);
-
NSLog(@"retainStr addr = %p",retainStr);
- NSLog(@"copyStr addr = %p",copyStr);
- NSLog(@"mcopyStr addr = %p",mcopyStr);
- str addr = 0x4598
- retainStr addr = 0x4598
- copyStr addr = 0x4598
- mcopyStr addr = 0x8caf630
分析:
retain的物件毫無懸念,還是源物件的記憶體地址;
copy的物件和我原來想的不一樣,竟然和retain一樣,也是源物件地址;這意味者並沒有對源物件內容進行復制,而只是複製了指標而已。如此看來copy方法並不一定會複製源物件的內容。之所以複製,肯定是因為兩個版本有所不同。而這裡源物件是NSString不可變的,copy返回的也是不可變的,既然都不可變,那麼這裡的副本就沒有多大意義存在,就如同使用字串常量,系統會為我們優化,宣告多個字串,都是不可變且內容相同,那麼系統就只申請一塊記憶體,這個道理是一樣的。指向一塊記憶體就可以了,所以這裡的copy和retain的作用是一樣的。
mutablecopy的物件地址和源物件地址不同,說明重新開闢了記憶體,複製了一個副本。因為mutablecopy返回的物件是可變的,它的變動會影響到源物件,所以需要拷貝一份。
源物件為可變的NSMutableString
- NSMutableString* str = [NSMutableString stringWithString:@"test"];
- NSString* retainStr = [str retain];
- NSString* copyStr = [str copy];
- NSMutableString* mcopyStr = [str mutableCopy];
- NSLog(@"str addr = %p",str);
- NSLog(@"retainStr addr = %p",retainStr);
- NSLog(@"copyStr addr = %p",copyStr);
- NSLog(@"mcopyStr addr = %p",mcopyStr);
- str addr = 0x8b7a130
- retainStr addr = 0x8b7a130
- copyStr addr = 0x8b751d0
- mcopyStr addr = 0x8b7a170
分析:
retain仍然和目的物件地址相同;
copy的地址和目的物件地址不相同,是因為源物件是可變的,目的物件不可變,當然需要兩個不同的版本;
mutablecopy形成了一個新的副本。因為兩個物件的改變會影響到對方,所以需要兩個版本。
得到的結論:
1、對於copy來說,如果源物件是不可變的,那麼是淺拷貝,沒有必要深拷貝;如果源物件可變,為了安全性,深拷貝,生成副本。
2、對於mutablecopy來說,不管源物件是否可變,都是深拷貝。
因此我們在設定property的copy屬性時,如果希望物件跟著源物件的值變化,那麼就是用retain;如果希望物件保持獨立的值,那就使用copy。當然這是在源物件為可變的情況下。
上面討論的是NSString相關的retain/copy/mutablecopy,在oc裡面所有實現了NSCopying和NSMutableCopying協議的類,都具有copy和mutablecopy這兩個方法。這裡引出了其他的oc物件的copy特性,它們是什麼樣的,下一篇進行探究。
歡迎指正!