淺入深出Copy和mutableCopy
- 2019 年 10 月 8 日
- 筆記
拷貝的目的
拷貝出一個和原對象的相同的副本,互不影響
舉個例子
NSString *a = [NSString stringWithFormat:@"abcabcabc"]; NSString *b = [a copy]; NSString *c = [a mutableCopy]; NSLog(@"%@,%@,%@",a,b,c); NSLog(@"%p,%p,%p",a,b,c);
輸出結果:
abcabcabc,abcabcabc,abcabcabc 0xf9f7789ebc9c00cc,0xf9f7789ebc9c00cc,0x6000011f7090
疑問
- 為什麼a 和b 地址一樣
- 我們思考一下,由於a 為不可變字元串,本身就是不可以改變的。所以只需要拷貝一個新的指針去指向a指向的地址就可以了。而c是a
mutableCopy得來的。因為變成NSMutableString而且不影響之前的對象,所以要拷貝出一個新的記憶體空間。
- 我們思考一下,由於a 為不可變字元串,本身就是不可以改變的。所以只需要拷貝一個新的指針去指向a指向的地址就可以了。而c是a
所以這裡就引出一個概念
- 深拷貝
- 內容拷貝
- 創建新對象
- 淺拷貝
- 指針拷貝
- 引用計數+1
- 為什麼淺拷貝要引入計數+1 因為a 和 b 指向同一個記憶體地址。如果不引用計數+1,會造成[a release]的時候 a對應的空間引用計數為0,造成釋放。而此時b 還在引用釋放的記憶體空間,就會產生壞記憶體訪問的崩潰現象
其他拷貝對象同理
不可變copy 為淺拷貝
注意
Tagged Pointer對象比較特殊。不用管理引用計數。
NSString *a = [NSString stringWithFormat:@"abc"]; NSLog(@"a retainCount = %ld",[a retainCount]); NSString *b = [a copy]; NSLog(@"a retainCount = %ld",[a retainCount]); NSString *c = [a mutableCopy]; NSLog(@"%@,%@,%@",a,b,c); NSLog(@"%p,%p,%p",a,b,c);
結果
2019-09-12 13:54:58.109757+0800 Copy MutableCopy[13700:49429440] a retainCount = -1 2019-09-12 13:54:58.109876+0800 Copy MutableCopy[13700:49429440] a retainCount = -1 2019-09-12 13:54:58.109989+0800 Copy MutableCopy[13700:49429440] abc,abc,abc 2019-09-12 13:54:58.110062+0800 Copy MutableCopy[13700:49429440] 0xd5e0520931336344,0xd5e0520931336344,0x6000038d3330
由Tagged Pointed 可以知道a b 為Tagged Pointer 對象 想深入了解的的可以看一下我的上一篇文章
總結
NSString | NSMutableString | NSArray | NSMutablArray | NSDictionary | NSMutableDictionary | |
|---|---|---|---|---|---|---|
copy | 淺拷貝 | 深拷貝 | 淺拷貝 | 深拷貝 | 淺拷貝 | 深拷貝 |
mutableCopy | 深拷貝 | 深拷貝 | 深拷貝 | 深拷貝 | 深拷貝 | 深拷貝 |