深淺拷貝iOS中的

 淺 復 :在複製操作時,對於被複制的對象的每一層複製都是指針複製。

   深 復 :在複製操作時,對於被複制的對象至少有一層複製是對象複製。

   完全複製:在複製操作時,對於被複制的對象的每一層複製都是對象複製。


        注:1在複製操作時,對於對象有n層是對象複製,我們可稱作n級深複製,此處n應大於等於1

             2對於完全複製如何實現(目前通用的辦法是:迭代法和歸檔),這裏後續是否添加視情況而定

                                暫時不做講解。

             3、指針複製俗稱指針拷貝,對象複製也俗稱內容拷貝。

             4、一般來講,

                              淺層複製:複製引用對象的指針。

                               深層複製:複製引用對象內容。

           這種定義在多層複制的時候,就顯得模糊。所以本文定義與它並不矛盾。
            反而是對它的進一步理解和說明。           


retain:始終是淺複製。引用計數每次加一。返回對象是否可變與被複制的對象保持一致。


copy:對於可變對象爲深複製,引用計數不改變;對於不可變對象是淺複製,

         引用計數每次加一。始終返回一個不可變對象。


mutableCopy:始終是深複製,引用計數不改變。始終返回一個可變對象。


不可變對象:值發生改變,其內存首地址隨之改變。

   可變對象:無論值是否改變,其內存首地址都不隨之改變。

   引用計數:爲了讓使用者清楚的知道,該對象有多少個擁有者(即有多少個指針指向同一內存地址)。


最近有一個好朋友問我,什麼時候用到深淺複製呢?那麼我就把我所總結的一些分享給大家,希望能幫助你們更好的理解深淺複製喔!


那麼先讓我們來看一看下邊數組類型的轉換

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];

 

   通俗的講,就是甲在執行交通導航任務,但接到上級新的命令要執行新的任務,那麼在甲執行新任務之前,需要有人替代甲繼續執行交通導航任務。這時候就要用到淺拷貝了。

則簡化爲:

問:什麼時候用到深淺拷貝?

答:深拷貝是在要將一個對象從可變(不可變)轉爲不可變(可變)或者將一個對象內容克隆一份時用到;

     淺拷貝是在要複製一個對象的指針時用到。



親愛的讀者朋友,下面是我用於驗證的詳細代碼。對於驗證還能得出什麼結論,我希望朋友們能自己多多發掘一下。這裏只做以上幾點總結。對於本文有任何疑問請與我聯繫,歡迎指出本文不足的地方,謝謝!

#import<Foundation/Foundation.h>


int main (int argc, const char * argv[])

{


    @autoreleasepool {


    //第一種:非容器類不可變對象


        NSString *str1=@"one day";

        

          printf("\n初始化賦值引用計數爲::::%lu",str1.retainCount);

        NSString *strCopy1=[str1 retain];

          printf("\n繼續retain引用計數爲:::%lu",str1.retainCount);

        NSString *strCopy2=[str1 copy];

          printf("\n繼續copy後引用計數爲::::%lu",str1.retainCount);

        NSString *strCopy3=[str1 mutableCopy];

                printf("\n繼續mutableCopy後爲:::%lu\n",str1.retainCount);

        

        printf("\n非容器類不可變對象\n原始地址::::::::::%p",str1);

        printf("\nretain複製::::::


  printf("\ncopy複製::::::::::%p",strCopy2);

        printf("\nmutableCopy複製:::%p",strCopy3);


    //這裏說明該類型不存在引用計數的概念


  // 初始化賦值引用計數爲:18446744073709551615

  // 繼續retain引用計數爲:18446744073709551615

  // 繼續copy後引用計數爲:18446744073709551615

  // 繼續mutableCopy後爲:18446744073709551615

   

   //非容器類不可變對象

   //原始地址::::::::::0x1000033d0

   //retain複製::::::::0x1000033d0//淺複製

   //copy複製::::::::::0x1000033d0//淺複製

   //mutableCopy複製:::0x10010c420//深複製

  


      printf("\n");

 //第二種:容器類不可變數組


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

        

          printf("\n初始化賦值引用計數爲::::::::::::%lu",array1.retainCount);

        NSArray *arrayCopy1 = [array1 retain];

          printf("\n繼續retain後引用計數爲:::::::::%lu",array1.retainCount);

        NSArray *arrayCopy2 = [array1 copy];

          printf("\n繼續copy後引用計數爲:::::::::::%lu",array1.retainCount);

        NSArray *arrayCopy3 = [array1 mutableCopy];

          printf("\n繼續mutableCopy後引用計數爲::::%lu\n",array1.retainCount);

        

    printf("\n容器類不可變數組\n原始地址::::::::::%p\t\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


    //容器類不可變數組

    //原始地址::::::::::0x10010c6b0 0x100003410

    //retain複製::::::::0x10010c6b0 0x100003410//複製

    //copy複製::::::::::0x10010c6b0 0x100003410//複製

    //mutableCopy複製:::0x10010c760 0x100003410//複製


    

        printf("\n");

 //第三種:非容器類可變對象


        NSMutableString *str2=[NSMutableString stringWithString:@"two day"];

        

          printf("\n初始化賦值引用計數爲::::::::::::%lu",str2.retainCount);

        NSMutableString *strCpy1=[str2 retain];

          printf("\n繼續retain後引用計數爲:::::::::%lu",str2.retainCount);

        NSMutableString *strCpy2=[str2 copy];

          printf("\n繼續copy後引用計數爲:::::::::::%lu",str2.retainCount);

        NSMutableString *strCpy3=[str2 mutableCopy];

                printf("\n繼續mutableCopy後引用計數爲::::%lu\n",str2.retainCount);

        

        printf("\n非容器類可變對象\n原始地址::::::::::%p",str2);

        printf("\nretin複製::::::::%p",strCpy1);

        printf("\ncopy複製::::::::::%p",strCpy2);

        printf("\nmutableCopy複製:::%p",strCpy3);

       

 


         //初始化賦值引用計數爲::::::::::::1

         //繼續retain後引用計數爲:::::::::2

         //繼續copy後引用計數爲:::::::::::2

         //繼續mutableCopy後引用計數爲::::2

 //非容器類可變對象

         //原始地址::::::::::0x10010c560

         //retain複製::::::::0x10010c560//複製

         //copy複製::::::::::0x100102720//複製

       //mutableCopy複製:::0x10010c880//複製

         

        printf("\n");

 //第四種:容器類可變數組


  NSMutableArray *array2   = [NSMutableArray arrayWithObjects:@"aa",@"bb",@"cc",@"dd",nil];

        

         printf("\n初始化賦值引用計數爲::::::::::%lu",array2.retainCount);

       NSMutableArray *arrayCpy1 = [array2 retain];

         printf("\n繼續retain後引用計數爲:::::::%lu",array2.retainCount);

       NSMutableArray *arrayCpy2=[array2 copy];

         printf("\n繼續copy後引用計數爲:::::::::%lu",array2.retainCount);

       NSMutableArray *arrayCpy3 = [array2 mutableCopy];

         printf("\n繼續mutableCopy後引用計數爲::%lu\n",array2.retainCount);

        

       printf("\n容器類可變數組\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


         //容器類可變數組

         //原始地址:::::::::::0x10010e6c0 0x1000034b0

         //retain複製:::::::::0x10010e6c0 0x1000034b0//淺複製

         //copy複製:::::::::::0x10010e790 0x1000034b0//複製

         //nmutableCopy複製:::0x10010e7c0 0x1000034b0//複製

                  }

        return 0;


}




 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章