iOS深拷貝與淺拷貝

2021-09-22 16:36:06 字數 3156 閱讀 4034

在大部分的程式語言中,都有深拷貝與淺拷貝的概念,如果使用深淺拷貝有誤,可能會造成資料安全性的問題,那麼本節針對oc中的深淺拷貝展開討論

深拷貝與淺拷貝的概念

我們在進行例項物件操作時,無非是兩種例項方式:

建立新物件後將原物件的內容拷貝乙份,而後返回該物件引用

深淺拷貝的區別由此產生:

以下是b物件拷貝a物件時,深淺拷貝的示意圖:

那麼根據上圖,我們可以推論,淺拷貝方式下,如果a物件指向的記憶體空間上的值改變,也會影響b物件,即造成了安全性問題。深拷貝方式下,則不會有這種問題。那麼既然淺拷貝會造成安全性問題,為何還要保留它呢?別急,且看下文。

不同型別物件下的深淺拷貝

在本節中,我們將oc中的物件分為四類:

可變非容器物件,例如nsmutablestring,nsmutablearray等

不可變非容器物件,例如nsstring,nsarray等

可變容器物件,例如nsmutablearray,nsmutabledictionary等

不可變容器物件,例如nsarray,nsdictionary等

在oc中,物件有兩種拷貝的方式,即呼叫copy與mutablecopy方法。使用不同型別物件呼叫這兩種方法,產生的拷貝型別(即深拷貝或淺拷貝)是不同的。

下圖是不同型別物件分別呼叫copy與mutablecopy後產生的拷貝型別:

案例分析

接下來我們通過不同案例來對不同型別物件下的拷貝及原因進行分析

1. 不可變非容器物件下的拷貝

nsstring *originalstr = @"something";

nsmutablestring *copystr = [originalstr copy];

nsmutablestring *mutablestr = [originalstr mutablecopy];

nslog(@"%p %p %p %@ %@",originalstr,copystr,mutablestr,[copystr class],[mutablestr class]);

輸出

0x1084530f0 0x1084530f0 0x600000269cc0 __nscfconstantstring __nscfstring
那麼通過這個案例,我們可以證明如下結論:

2. 可變非容器物件下的拷貝

nsmutablestring *originalstr = [nsmutablestring stringwithstring:@"something"];

nsmutablestring *copystr = [originalstr copy];

nsmutablestring *mutablestr = [originalstr mutablecopy];

nslog(@"%p %p %p %@ %@",originalstr,copystr,mutablestr,[copystr class],[mutablestr class]);

輸出

0x60800007ee80 0xa0c0c60045412da9 0x60800007edc0 nstaggedpointerstring __nscfstring
那麼通過這個案例,我們可以證明如下結論:

3. 不可變容器物件下的拷貝

nsarray *originalarr = @[@1,@2,@[@3,@4]];

nsmutablearray *copyarr = [originalarr copy];

nsmutablearray *mutablearr = [originalarr mutablecopy];

nslog(@"%p %p %p %@ %@",originalarr,copyarr,mutablearr,[copyarr class],[mutablearr class]);

輸出

0x60800005c4d0 0x60800005c4d0 0x60800005c560 __nsarrayi __nsarraym
那麼通過這個案例,我們可以證明如下結論:

4. 可變容器物件下的拷貝

nsmutablearray *originalarr = [[nsmutablearray alloc] initwithobjects:@1,@2,@[@3,@4], nil];

nsmutablearray *copyarr = [originalarr copy];

nsmutablearray *mutablearr = [originalarr mutablecopy];

nslog(@"%p %p %p %@ %@",originalarr,copyarr,mutablearr,[copyarr class],[mutablearr class]);

輸出

0x60000004ad10 0x60000004aef0 0x60000004ae60 __nsarrayi __nsarraym
那麼通過這個案例,我們可以證明如下結論:

經典面試題

看完了上面的內容,我們來回答乙個面試題:為什麼nsstring的屬性一般都是使用copy修飾?

假設使用copy修飾了乙個nsstring物件:

@property (nonatomic,copy) nsstring *str;
那麼系統會給str物件自動生成setter方法,模擬setter實現**如下:

- (void)setter:(nsstring *)strnew 

}

觀察setter方法,我們發現使用copy後,淺拷貝了該strnew物件,即str指向了strnew指向的那塊記憶體,避免了記憶體浪費。

結束關於深拷貝與淺拷貝個人的理解到此結束,作者水平有限,文中可能存在錯誤,敬請諒解指教。

歌曲推薦:家後-江蕙

iOS偽拷貝, 淺拷貝, 深拷貝

先來說說偽拷貝。偽拷貝就是生成了乙個指標變數,指向了某乙個物件。接下來我們來 下淺拷貝和深拷貝。首先,從copy開始說,簡而言之,copy的目的就是生成乙個新的例項,然後把其成員都按原例項賦值。對於非指標型的成員,比如bool,int,float,這樣的賦值可以直接進行。但是對於指標型的資料,比如o...

iOS 深拷貝淺拷貝例項

nsstring string 漢斯哈哈哈 沒有產生新物件 nsstring copystring string copy 產生新物件 nsmutablestring mutablecopystring string mutablecopy nslog string p copystring p m...

「淺拷貝」與「深拷貝」

c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...