OC-深浅复制
【OC學(xué)習(xí)-26】對象的淺拷貝和深拷貝——關(guān)鍵在于屬性是否可被拷貝
拷貝用到協(xié)議,如果這個類創(chuàng)建對象后,這個對象要被拷貝,那么這個類就需要用到拷貝協(xié)議,分兩種:<NSCopying>和<NSMutableCopying>相當(dāng)于一個是拷貝,另一個是拷貝后可修改。
?
(1)淺拷貝的案例。有一個Person類,它創(chuàng)建一個person1對象后,用person1再拷貝一個person2出來。
//Person類的Person.h文件 #import <Foundation/Foundation.h> //因為這個類要支持拷貝,所以需要引入拷貝協(xié)議,有兩種,后一種拷貝后可修改 @interface Person : NSObject<NSCopying,NSMutableCopying> @property(nonatomic,copy) NSString* name; @property(nonatomic,retain) NSNumber* age; @end //這是Person.m文件 #import "Person.h" @implementation Person //這是系統(tǒng)函數(shù),可以直接拷貝過來 - (id)copyWithZone:(NSZone *)zone{ Person *person=[[[self class]allocWithZone:zone]init]; //默認(rèn)格式 person.name=_name; //淺拷貝就是直接賦值即可 person.age=_age; //淺拷貝就是直接賦值即可 return person; } @end //main.m文件 #import <Foundation/Foundation.h> #import "Person.h"//記得引入頭文件 int main(int argc, const char * argv[]) { @autoreleasepool { Person *person1=[[Person alloc]init]; person1.name=@"jack"; person1.age=@18; Person *person2=[person1 copy]; NSLog(@"%p,%p",person1,person2);//輸入兩個對象地址,不同 NSLog(@"%p,%p",person1.age,person2.age);//輸出兩個對象的屬性地址,相同 } return 0; }結(jié)果:
0x1002036f0,0x100200330 //不同 0x1227,0x1227 //相同(2)深拷貝的案例。
按道理是只需要把Person.m里面的賦值語句改成下面的樣子,就能實現(xiàn)深拷貝:
person.name=[_name copy]; person.age=[_age copy];但是,因為cocoa優(yōu)化過了,所以有如下規(guī)則:
a:如果是Foundation框架里的不可變對象,就是Array,NSString等創(chuàng)建的對象,直接用copy來拷貝相當(dāng)于retain,也就是屬性還是同一個;
b:如果是用mutableCopy來拷貝,不管是可變還是不可變對象,屬性神馬的都直接拷貝了一份,即真正意義上得拷貝,它拷貝出來的對象統(tǒng)統(tǒng)都是可變的;
c:如果是可變對象,我們用copy也能實現(xiàn)真正意義上的拷貝,但是拷貝出來的對象是不可變的。
所以,我們拿name實驗(因為age沒有mutableCopy)實現(xiàn)語句的修改:
person.name=[_name mutableCopy] person.age=[_age copy];然后再輸出person1和person2的name屬性的地址,發(fā)現(xiàn)就不同了。
總結(jié):
淺拷貝和深拷貝在實際項目中不常用,可以做一般了解。
?
?
?
OC-深淺復(fù)制
???淺 復(fù)?制:在復(fù)制操作時,對于被復(fù)制的對象的每一層復(fù)制都是指針復(fù)制。
???深 復(fù)?制:在復(fù)制操作時,對于被復(fù)制的對象至少有一層復(fù)制是對象復(fù)制。
???完全復(fù)制:在復(fù)制操作時,對于被復(fù)制的對象的每一層復(fù)制都是對象復(fù)制。
?
????????注:1、在復(fù)制操作時,對于對象有n層是對象復(fù)制,我們可稱作n級深復(fù)制,此處n應(yīng)大于等于1。
??????????????2、對于完全復(fù)制如何實現(xiàn)(目前通用的辦法是:迭代法和歸檔),這里后續(xù)是否添加視情況而定,
??????????????暫時不做講解。
??????????3、指針復(fù)制俗稱指針拷貝,對象復(fù)制也俗稱內(nèi)容拷貝。
?
retain:始終是淺復(fù)制。引用計數(shù)每次加一。返回對象是否可變與被復(fù)制的對象保持一致。
?
copy:對于可變對象為深復(fù)制,引用計數(shù)不改變;對于不可變對象是淺復(fù)制,
?????????引用計數(shù)每次加一。始終返回一個不可變對象。
?
mutableCopy:始終是深復(fù)制,引用計數(shù)不改變。始終返回一個可變對象。
?
不可變對象:值發(fā)生改變,其內(nèi)存首地址隨之改變。
???可變對象:無論值是否改變,其內(nèi)存首地址都不隨之改變。
???引用計數(shù):為了讓使用者清楚的知道,該對象有多少個擁有者(即有多少個指針指向同一內(nèi)存地址)。
?
親愛的讀者朋友,下面是我用于驗證的詳細(xì)代碼。對于驗證還能得出什么結(jié)論,我希望朋友們能自己多多發(fā)掘一下。這里只做以上幾點總結(jié)。對于本文有任何疑問請與我聯(lián)系,歡迎指出本文不足的地方,謝謝!
#import<Foundation/Foundation.h>
?
int?main (int?argc,?const?char?* argv[])
{
?
????@autoreleasepool?{
?
????//第一種:非容器類不可變對象
?
????????NSString?*str1=@"one day";
????????
??????????printf("n初始化賦值引用計數(shù)為::::%lu",str1.retainCount);
????????NSString?*strCopy1=[str1?retain];
??????????printf("n繼續(xù)retain引用計數(shù)為:::%lu",str1.retainCount);
????????NSString?*strCopy2=[str1?copy];
??????????printf("n繼續(xù)copy后引用計數(shù)為::::%lu",str1.retainCount);
????????NSString?*strCopy3=[str1?mutableCopy];
????????????????printf("n繼續(xù)mutableCopy后為:::%lun",str1.retainCount);
????????
????????printf("n非容器類不可變對象n原始地址::::::::::%p",str1);
????????printf("nretain復(fù)制::::::::%p",strCopy1);
????????printf("ncopy復(fù)制::::::::::%p",strCopy2);
????????printf("nmutableCopy復(fù)制:::%p",strCopy3);
?
????//這里說明該類型不存在引用計數(shù)的概念
?
??//?初始化賦值引用計數(shù)為:18446744073709551615
??//?繼續(xù)retain引用計數(shù)為:18446744073709551615
??//?繼續(xù)copy后引用計數(shù)為:18446744073709551615
??//?繼續(xù)mutableCopy后為:18446744073709551615
???
???//非容器類不可變對象
???//原始地址::::::::::0x1000033d0
???//retain復(fù)制::::::::0x1000033d0//淺復(fù)制
???//copy復(fù)制::::::::::0x1000033d0//淺復(fù)制
???//mutableCopy復(fù)制:::0x10010c420//深復(fù)制
??
?
??????printf("n");
?//第二種:容器類不可變數(shù)組
?
????????NSArray?*array1= [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",nil];
????????
??????????printf("n初始化賦值引用計數(shù)為::::::::::::%lu",array1.retainCount);
????????NSArray?*arrayCopy1 = [array1?retain];
??????????printf("n繼續(xù)retain后引用計數(shù)為:::::::::%lu",array1.retainCount);
????????NSArray?*arrayCopy2 = [array1?copy];
??????????printf("n繼續(xù)copy后引用計數(shù)為:::::::::::%lu",array1.retainCount);
????????NSArray?*arrayCopy3 = [array1?mutableCopy];
??????????printf("n繼續(xù)mutableCopy后引用計數(shù)為::::%lun",array1.retainCount);
????????
????printf("n容器類不可變數(shù)組n原始地址::::::::::%ptt%p",array1,[array1 objectAtIndex:1]);
????????printf("nretain復(fù)制::::::::%pt%p",arrayCopy1,[arrayCopy1?objectAtIndex:1]);
????????printf("ncopy復(fù)制::::::::::%pt%p",arrayCopy2,[arrayCopy2?objectAtIndex:1]);
????????printf("nmutableCopy復(fù)制:::%pt%p",arrayCopy3,[arrayCopy3?objectAtIndex:1]);
????????
???
????//初始化賦值引用計數(shù)為::::::::::::1
????//繼續(xù)retain后引用計數(shù)為:::::::::2
????//繼續(xù)copy后引用計數(shù)為:::::::::::3
????//繼續(xù)mutableCopy后引用計數(shù)為::::3
?
????//容器類不可變數(shù)組
????//原始地址::::::::::0x10010c6b0 0x100003410
????//retain復(fù)制::::::::0x10010c6b0 0x100003410//淺復(fù)制
????//copy復(fù)制::::::::::0x10010c6b0 0x100003410//淺復(fù)制
????//mutableCopy復(fù)制:::0x10010c760 0x100003410//深復(fù)制
?
????
????????printf("n");
?//第三種:非容器類可變對象
?
????????NSMutableString?*str2=[NSMutableString?stringWithString:@"two day"];
????????
??????????printf("n初始化賦值引用計數(shù)為::::::::::::%lu",str2.retainCount);
????????NSMutableString?*strCpy1=[str2?retain];
??????????printf("n繼續(xù)retain后引用計數(shù)為:::::::::%lu",str2.retainCount);
????????NSMutableString?*strCpy2=[str2?copy];
??????????printf("n繼續(xù)copy后引用計數(shù)為:::::::::::%lu",str2.retainCount);
????????NSMutableString?*strCpy3=[str2?mutableCopy];
????????????????printf("n繼續(xù)mutableCopy后引用計數(shù)為::::%lun",str2.retainCount);
????????
????????printf("n非容器類可變對象n原始地址::::::::::%p",str2);
????????printf("nretin復(fù)制::::::::%p",strCpy1);
????????printf("ncopy復(fù)制::::::::::%p",strCpy2);
????????printf("nmutableCopy復(fù)制:::%p",strCpy3);
???????
?
?
?????????//初始化賦值引用計數(shù)為::::::::::::1
?????????//繼續(xù)retain后引用計數(shù)為:::::::::2
?????????//繼續(xù)copy后引用計數(shù)為:::::::::::2
?????????//繼續(xù)mutableCopy后引用計數(shù)為::::2
?
?????????//非容器類可變對象
?????????//原始地址::::::::::0x10010c560
?????????//retain復(fù)制::::::::0x10010c560//淺復(fù)制
?????????//copy復(fù)制::::::::::0x100102720//深復(fù)制
???????//mutableCopy復(fù)制:::0x10010c880//深復(fù)制
?????????
????????printf("n");
?//第四種:容器類可變數(shù)組
?
??NSMutableArray?*array2 ??= [NSMutableArrayarrayWithObjects:@"aa",@"bb",@"cc",@"dd",nil];
????????
?????????printf("n初始化賦值引用計數(shù)為::::::::::%lu",array2.retainCount);
???????NSMutableArray?*arrayCpy1 = [array2?retain];
?????????printf("n繼續(xù)retain后引用計數(shù)為:::::::%lu",array2.retainCount);
???????NSMutableArray?*arrayCpy2=[array2?copy];
?????????printf("n繼續(xù)copy后引用計數(shù)為:::::::::%lu",array2.retainCount);
???????NSMutableArray?*arrayCpy3 = [array2?mutableCopy];
?????????printf("n繼續(xù)mutableCopy后引用計數(shù)為::%lun",array2.retainCount);
????????
???????printf("n容器類可變數(shù)組n原始地址:::::::::::%pt%p",array2,[array2 objectAtIndex:1]);
???????printf("nretain復(fù)制:::::::::%pt%p",arrayCpy1,[arrayCpy1?objectAtIndex:1]);
???????printf("ncopy復(fù)制:::::::::::%pt%p",arrayCpy2,[arrayCpy2?objectAtIndex:1]);
???????printf("nnmutableCopy復(fù)制:::%pt%p",arrayCpy3,[arrayCpy3?objectAtIndex:1]);
???????
????????
?????????//初始化賦值引用計數(shù)為::::::::::1
?????????//繼續(xù)retain后引用計數(shù)為:::::::2
?????????//繼續(xù)copy后引用計數(shù)為:::::::::2
?????????//繼續(xù)mutableCopy后引用計數(shù)為::2
?
?????????//容器類可變數(shù)組
?????????//原始地址:::::::::::0x10010e6c0 0x1000034b0
?????????//retain復(fù)制:::::::::0x10010e6c0 0x1000034b0//淺復(fù)制
?????????//copy復(fù)制:::::::::::0x10010e790 0x1000034b0//深復(fù)制
?????????//nmutableCopy復(fù)制:::0x10010e7c0 0x1000034b0//深復(fù)制
?????????
????????
?
????}
????return 0;
}
?
轉(zhuǎn)載于:https://www.cnblogs.com/iOS-mt/p/4121583.html
總結(jié)
- 上一篇: 移植深度学习算法模型到海思AI芯片
- 下一篇: 最近天气凉快了,西安有什么带孩子去玩的好