关于浅拷贝、深拷贝的探究
淺拷貝、深拷貝、完全拷貝
在這里介紹三個概念:
淺拷貝:在拷貝操作時,對于被拷貝的對象的每一層拷貝都是指針拷貝。
深拷貝:在拷貝操作時,對于被拷貝的對象至少有一層拷貝是對象拷貝。
完全拷貝:在拷貝操作時,對于被拷貝的對象的每一層拷貝都是對象拷貝。
- 1.在拷貝操作時,對于對象有n層是對象拷貝,我們可稱作n級深拷貝,此處n應大于等于1。
- 2.對于完全拷貝如何實現(目前通用的辦法是:迭代法和歸檔),這里后續是否添加視情況而定,暫時不做講解。
- 3.指針拷貝俗稱指針拷貝,對象拷貝也俗稱內容拷貝。
- 4.一般來講,淺層拷貝, 拷貝引用對象的指針;深層拷貝, 拷貝引用對象內容。這種定義在多層拷貝的時候,就顯得模糊。所以本文定義與它并不矛盾。反而是對它的進一步理解和說明。
深淺拷貝對比
上面說了, 關于 copy, 對于不可變對象是淺拷貝,引用計數每次加一。始終返回一個不可變對象; 對于可變對象為深拷貝,引用計數不改變。所以我們就按照可變和不可變來分別介紹, 由于還涉及到深拷貝和完全拷貝, 所以又按照容器類和非容器類分別來介紹。故分了四大類:非容器類不可變對象, 容器類不可變數組, 非容器類可變對象, 容器類可變數組。
注: 下面整理的 demo 中str1用的是常量區的字符串, 所以在引用計數時, 會是無窮大。 如果有興趣可以改為堆區對象, 這樣引用計數會正常。 其他的方面不會影響到本測試。
非容器類不可變對象
NSString *str1=[NSString stringWithFormat:@"我屮艸芔茻"]; // NSString *str1=@"one day";printf("\n初始化引用計數為:%lu",str1.retainCount); NSString *strCopy1=[str1 retain]; printf("\nretain引用計數為:%lu",str1.retainCount); NSString *strCopy2=[str1 copy]; printf("\ncopy后引用計數為:%lu",str1.retainCount); NSString *strCopy3=[str1 mutableCopy]; printf("\n繼續mutableCopy后為:%lu\n",str1.retainCount);printf("\n非容器類不可變對象"); printf("\n原始地址:%p",str1); printf("\nretain拷貝:%p",strCopy1); printf("\ncopy拷貝:%p",strCopy2); printf("\nmutableCopy拷貝:%p",strCopy3);打印結果:
初始化引用計數為:1
retain引用計數為:2
copy后引用計數為:3
繼續mutableCopy后為:3
非容器類不可變對象
原始地址:_0x60400025c260
retain拷貝:0x60400025c260
copy拷貝:0x60400025c260
mutableCopy拷貝:0x600000059c20
容器類不可變對象
NSArray *array1= [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",nil];printf("\n初始化引用計數為:%lu",array1.retainCount); NSArray *arrayCopy1 = [array1 retain]; printf("\nretain后引用計數為:%lu",array1.retainCount); NSArray *arrayCopy2 = [array1 copy]; printf("\ncopy后引用計數為:%lu",array1.retainCount); NSArray *arrayCopy3 = [array1 mutableCopy]; printf("\nmutableCopy后引用計數為:%lu\n",array1.retainCount);printf("\n容器類不可變數組"); printf("\n原始地址:%p\t%p",array1,[array1 objectAtIndex:1]); printf("\nretain拷貝:%p\t%p",arrayCopy1,[arrayCopy1 objectAtIndex:1]); printf("\ncopy拷貝:%p\t%p",arrayCopy2,[arrayCopy2 objectAtIndex:1]); printf("\nmutableCopy拷貝:%p\t%p",arrayCopy3,[arrayCopy3 objectAtIndex:1]);打印結果:
初始化引用計數為:1
retain后引用計數為:2
copy后引用計數為:3
mutableCopy后引用計數為:3
容器類不可變數組
原始地址:0x600000444050 0x10fef20b0
retain拷貝:0x600000444050 0x10fef20b0
copy拷貝:0x600000444050 0x10fef20b0
mutableCopy拷貝:0x600000444170 0x10fef20b0
非容器類可變對象
NSMutableString *str2=[NSMutableString stringWithString:@"two day"];printf("\n初始化引用計數為:%lu",str2.retainCount); NSMutableString *strCpy1=[str2 retain]; printf("\nretain后引用計數為:%lu",str2.retainCount); NSMutableString *strCpy2=[str2 copy]; printf("\ncopy后引用計數為:%lu",str2.retainCount); NSMutableString *strCpy3=[str2 mutableCopy]; printf("\nmutableCopy后引用計數為:%lu\n",str2.retainCount);printf("\n非容器類可變對象"); printf("\n原始地址:%p",str2); printf("\nretin拷貝:%p",strCpy1); printf("\ncopy拷貝:%p",strCpy2); printf("\nmutableCopy拷貝:%p",strCpy3);打印結果:
初始化引用計數為:1
retain后引用計數為:2
copy后引用計數為:2
mutableCopy后引用計數為:2
非容器類可變對象
原始地址:0x6000004441a0
retin拷貝:_0x6000004441a0
copy拷貝:0xa796164206f77747
mutableCopy拷貝:0x600000444140
容器類可變對象
NSMutableArray *array2 = [NSMutableArray arrayWithObjects:@"aa",@"bb",@"cc",@"dd",nil];printf("\n初始化引用計數為:%lu",array2.retainCount); NSMutableArray *arrayCpy1 = [array2 retain]; printf("\nretain后引用計數為:%lu",array2.retainCount); NSMutableArray *arrayCpy2=[array2 copy]; printf("\ncopy后引用計數為:%lu",array2.retainCount); NSMutableArray *arrayCpy3 = [array2 mutableCopy]; printf("\nmutableCopy后引用計數為:%lu\n",array2.retainCount);printf("\n容器類可變數組"); printf("\n原始地址::%p\t%p",array2,[array2 objectAtIndex:1]); printf("\nretain拷貝:%p\t%p",arrayCpy1,[arrayCpy1 objectAtIndex:1]); printf("\ncopy拷貝:%p\t%p",arrayCpy2,[arrayCpy2 objectAtIndex:1]); printf("\nnmutableCopy拷貝:%p\t%p",arrayCpy3,[arrayCpy3 objectAtIndex:1]);打印結果:
初始化引用計數為:1
retain后引用計數為:2
copy后引用計數為:2
mutableCopy后引用計數為:2
容器類可變數組
原始地址::0x60400025c2f0 0x10fef2150
retain拷貝:_0x60400025c2f0 0x10fef2150
copy拷貝:_0x60400025c080 0x10fef2150
nmutableCopy拷貝:0x60400025bf90 0x10fef2150
應用
1、不可變對象→可變對象的轉換:
NSArray *array1= [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",nil]; NSMutableArray *str2=[array1 mutableCopy];2、可變對象→不可變對象的轉換:
NSMutableArray *array2 = [NSMutableArray arrayWithObjects:@"aa",@"bb",@"cc",@"dd",nil]; NSArray *array1 = [array2 Copy];3、可變對象→可變對象的轉換(不同指針變量指向不同的內存地址):
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"a",@"b",@"c",@"d",nil]; NSMutableArray *str2 = [array1 mutableCopy];通過上邊的兩個例子,我們可輕松的將一個對象在可變和不可變之間轉換,并且這里不用考慮內存使用原則(即引用計數的問題)。沒錯,這就是深拷貝的魅力了。
4、同類型對象之間的指針拷貝(不同指針變量指向同一塊內存地址):
//a、NSMutableString *str1 = [NSMutableString stringWithString:@"two day"];NSMutableString *str2 = [str1 retain];[str1 release];//b、NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",nil];NSArray *str2 = [array1 Copy];[array1 release];應用總結:
1.深拷貝是在要將一個對象從可變(不可變)轉為不可變(可變)或者將一個對象內容克隆一份時用到;
2.淺拷貝是在要拷貝一個對象的指針時用到。
3.深拷貝賦值過程:輸入數據→寄存器處理→開辟內存→寫入數據。
一次深拷貝,可以得到被拷貝對象指針,并進行一次賦值操作。
對于深拷貝和完全拷貝, 下篇文章深拷貝和完全拷貝對比的探究會具體談一談.
總結
以上是生活随笔為你收集整理的关于浅拷贝、深拷贝的探究的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021年河南省高考成绩位次查询,202
- 下一篇: PostgreSQL下载安装教程(及Po