iOS中深複製和淺複製問題

2021-07-22 13:10:15 字數 3651 閱讀 2048

nsdictionary

物件,新增內容,然後通過**產生可變和不可變副本,這些複製是深複製還是淺複製?那麼對於可變物件呢?為什麼nsstring定義屬性時需要用copy呢?copy屬性和copy物件有什麼不同?

首先先說一下

copy

和retain

的區別:

copy

是建立乙個新物件,是內容拷貝。

retain

是建立乙個指標,引用物件計數加1。

retain

屬性表示兩個物件位址相同(建立乙個指標,指標拷貝),內容當然相同,這個物件的

retain

值+1。

對於深複製和淺複製我們來看下面的**:

nsdictionary

*dict = [

nsdictionary

dictionarywithobjectsandkeys

:@"1"

,@"1"

,@"2"

,@"2"

,nil];

nslog(@"

原字典:%p"

,dict);

nsdictionary

*dictretain = dict.

retain;

nslog(@"

計數器:%p"

,dictretain);

nsdictionary

*dictcopy = dict.

copy;

nslog(@"

淺複製:%p"

,dictcopy);

nsmutabledictionary

*dictmutablecopy = dict.

mutablecopy;

nslog(@"

深複製:%p"

,dictmutablecopy);

列印結果:

原字典:0x7f7f89d21ec0

計數器:0x7f7f89d21ec0

淺複製:0x7f7f89d21ec0

深複製:0x7f7f89c09680

也就是說,

對於retain

和copy

產生的字典記憶體與原位址記憶體相同,也就是說

copy

產生的不可變版本是淺複製和

retain

一樣拷貝的是指標。而

mutablecopy

深複製是拷貝的物件內容。

下面我們看乙個可變物件的拷貝過程:

nsmutablestring

*string = [

nsmutablestring

stringwithstring

:@"name"];

nslog

(@"strp:%p"

,string);

nsstring

*stringcopy = [string

copy];

nslog

(@"copy:%p"

,stringcopy);

nsmutablestring

*mstringcopy = [string

copy];

nslog

(@"copy:%p"

,mstringcopy);

nsmutablestring

*stringmcopy = [string

mutablecopy];

nslog

(@"mcopy:%p"

,stringmcopy);

列印結果:

strp:0x7faea1f124d0

copy:0xa000000656d616e4

copy:0xa000000656d616e4

mcopy:0x7faea1e0df20

對於可變物件進行複製,結果和上面不一樣了。

我們可以這樣理解:

如果對一不可變物件複製,

copy

是指標複製(淺拷貝)和

mutablecopy

就是物件複製(深拷貝)。如果是對可變物件複製,都是深拷貝,但是

copy

返回的物件是不可變的。

還有乙個問題就是:我們知道,在

@property

屬性裡copy

說的是複製了乙個新的物件,引用計數不加

1.那麼這裡屬性

copy

則是使用了深複製。而呼叫

copy

方法則是做了乙個淺複製。

這也就是為什麼

nsstring

屬性變數要用

copy

關鍵字。

如果把乙個

nsstring

賦值給nsmutablestring

屬性時,如果使用了

strong,

則相當於淺複製。兩個指標指向同一塊記憶體,當

nsmutablestring

改變後,

nsstring

也就改變了。如果使用了

copy

,則是深複製。兩個物件存在於不同的記憶體中,當

nsmutablestring

改變時,不影響

nsstring.

另外,對於字串來說,我們在使用的時候還要注意:

initwithformat

會建立新空間,

initwithstring

不一定建立新空間,取決於引數。如果後面是常量字串則不會建立新空間,如果是定義新字串,則會建立新空間。

下面是測試**:

nsstring *name = [[nsstring alloc]initwithformat:@"

張三"];

nsstring

*name = [[

nsstring

alloc

]initwithstring:@"

張三"];

nslog

(@"%ld"

,[name

retaincount

]);

[name

retain];

nslog

(@"%ld"

,[name

retaincount

]);

[name

copy];

nslog

(@"%ld"

,[name

retaincount

]);

[name

mutablecopy];

nslog

(@"%ld"

,[name

retaincount])

結果:如果是

initwithstring,

則輸入結果全為

-1,如果是

initwithformat

,結果分別是

:1,2,3,4

iOS深複製和淺複製

淺複製示例 nsmutablearray marray nsmutablearray arraywithobjects nsmutablestring stringwithstring origiona nsmutablestring stringwithstring origionb nsmuta...

iOS 深複製和淺複製

一 copy與retain的區別 1 copy是建立乙個新物件,retain是建立乙個指標,引用物件計數加一。2 copy屬性表示兩個物件內容相同,新的物件retain為1,與舊有的物件的引用計數無關,舊有物件沒有改變。copy減少物件對上下文的依賴。3 retain屬性表示兩個物件位址相同 建立乙...

淺複製和深複製

在c 中,下面三種物件需要呼叫拷貝建構函式 有時也稱 複製建構函式 1 乙個物件作為函式引數,以值傳遞的方式傳入函式體 全域性函式,傳入的是物件 void g fun resume c 2 乙個物件作為函式返回值,以值傳遞的方式從函式返回 全域性函式 返回的是物件 resume g fun 3 乙個...