淺 復 制:在複製操作時,對於被複製的物件的每一層複製都是指標複製。
深 復 制:在複製操作時,對於被複製的物件至少有一層複製是物件複製。
完全複製:在複製操作時,對於被複製的物件的每一層複製都是物件複製。
注:1、在複製操作時,對於物件有n層是物件複製,我們可稱作n級深複製,此處n應大於等於1。
2、對於完全複製如何實現(目前通用的辦法是:迭代法和歸檔),這裡後續是否新增視情況而定,
暫時不做講解。
3、指標複製俗稱指標拷貝,物件複製也俗稱內容拷貝。
retain:始終是淺複製。引用計數每次加一。返回物件是否可變與被複製的物件保持一致。
copy:對於可變物件為深複製,引用計數不改變;
對於不可變物件是淺複製,
引用計數每次加一。始終返回乙個不可變物件。
mutablecopy:始終是深複製,引用計數不改變。始終返回乙個可變物件。
#import
int main (int argc, const char * argv)
return 0;
}如果容器類想實現完全深度用nscoding協議實現
nsarray *arr = [nsarray arraywithobjects:people, nil];
nsdata *data = [nskeyedarchiver archiveddatawithrootobject:arr];
nsarray *arr1 = [nskeyedunarchiver unarchiveobjectwithdata:data];
ios 深淺拷貝學習
首先我們需要有這樣的乙個前提:
[array addobject:obj];
這樣obj的引用計數會增加1,如果使用remove則obj的引用計數會減一。
ios對集合的記憶體處理就是這樣的。
那麼,假設obj只被array擁有:
id temp = [array objectatindex:0];
[array removeobjectatindex:0];
如果你再要使用temp就會出錯,因為這個時候obj已經被釋放了。
(提醒一下,如果用nsstring做測試,要注意@「abc」是常量 :-) )
由於在程式中經常會遇到集合類的傳值,所以,簡單的retain未必夠用,需要對集合內容的拷貝,也就是深拷貝。
下面我們就來**一下。
ios提供了copy和mutablecopy方法,顧名思義,copy就是複製了乙個imutable的物件,而mutablecopy就是複製了乙個mutable的物件。以下將舉幾個例子來說明。
1. 系統的非容器類物件
這裡指的是nsstring,nsnumber等等一類的物件。
nsstring *string = @"origion";
nsstring *stringcopy = [string copy];
nsmutablestring *stringmcopy = [string mutablecopy];
再看下面的例子:
nsmutablestring *string = [nsmutablestring stringwithstring: @"origion"];
nsstring *stringcopy = [string copy];
nsmutablestring *mstringcopy = [string copy];
nsmutablestring *stringmcopy = [string mutablecopy];
以上四個nsstring物件所分配的記憶體都是不一樣的。但是對於mstringcopy其實是個imutable物件,所以上述會報錯。
對於系統的非容器類物件,我們可以認為,如果對一不可變物件複製,copy是指標複製(淺拷貝)和mutablecopy就是物件複製(深拷貝)。如果是對可變物件複製,都是深拷貝,但是copy返回的物件是不可變的。
2. 系統的容器類物件
指nsarray,nsdictionary等。對於容器類本身,上面討論的結論也是適用的,需要**的是複製後容器內物件的變化。
//copy返回不可變物件,mutablecopy返回可變物件
nsarray *array1 = [nsarray arraywithobjects:@"a",@"b",@"c",nil];
nsarray *arraycopy1 = [array1 copy];
//arraycopy1是和array同乙個nsarray物件(指向相同的物件),包括array裡面的元素也是指向相同的指標
nslog(@"array1 retain count: %d",[array1 retaincount]);
nslog(@"array1 retain count: %d",[arraycopy1 retaincount]);
nsmutablearray *marraycopy1 = [array1 mutablecopy];
//marraycopy1是array1的可變副本,指向的物件和array1不同,但是其中的元素和array1中的元素指向的是同乙個物件。marraycopy1還可以修改自己的物件
[marraycopy1 addobject:@"de"];
[marraycopy1 removeobjectatindex:0];
array1和arraycopy1是指標複製,而marraycopy1是物件複製,marraycopy1還可以改變陣列內的元素:刪除或新增。但是注意的是,容器內的元素內容都是指標複製。
下面用另乙個例子來測試一下。
nsarray *marray1 = [nsarray arraywithobjects:[nsmutablestring stringwithstring:@"a"],@"b",@"c",nil];
nsarray *marraycopy2 = [marray1 copy];
nslog(@"marray1 retain count: %d",[marray1 retaincount]);
nsmutablearray *marraymcopy1 = [marray1 mutablecopy];
nslog(@"marray1 retain count: %d",[marray1 retaincount]);
//marraycopy2,marraymcopy1和marray1指向的都是不一樣的物件,但是其中的元素都是一樣的物件——同乙個指標
//一下做測試
nsmutablestring *teststring = [marray1 objectatindex:0];
//teststring = @"1a1";//這樣會改變teststring的指標,其實是將@「1a1」臨時物件賦給了teststring
nsarray *array = [nsarray arraywithobjects:[nsmutablestring stringwithstring:@"first"],[nsstringstringwithstring:@"b"],@"c",nil];
nsarray *deepcopyarray=[[nsarray alloc] initwitharray: array copyitems: yes];//對於array 巢狀array的情況 只能深層複製第一層
nsarray* truedeepcopyarray = [nskeyedunarchiver unarchiveobjectwithdata:
[nskeyedarchiver archiveddatawithrootobject: array]];
或者我們自己實現深拷貝的方法(略)。
3. 自定義物件
如果是我們定義的物件,那麼我們自己要實現nscopying,nsmutablecopying這樣就能呼叫copy和mutablecopy了。舉個例子:
@inte***ce myobj : nsobject
@property (nonatomic, retain) nsmutablestring *name;
@property (nonatomic, retain) nsstring *imutablestr;
@property (nonatomic) int age;
@end
@implementation myobj
@synthesize name;
@synthesize age;
@synthesize imutablestr;
- (id)init
return self;
}- (void)dealloc
- (id)copywithzone:(nszone *)zone
- (id)mutablecopywithzone:(nszone *)zone
@end
深度拷貝和淺度拷貝
文字說明 比如乙個陣列 array 淺度拷貝是當陣列a變數成陣列b的時候,b改變裡面的陣列數值的時候,a也隨著改變,深度拷貝是噹噹陣列a變數成陣列b的時候,b改變裡面的陣列數值的時候,a裡面的陣列陣列不隨著改變,那麼為什麼淺度拷貝會改變a的陣列值而深度拷貝則不會呢?因為淺度拷貝指向的是同乙個記憶體,...
C 預設拷貝建構函式 深度拷貝和淺拷貝
c 類的中有兩個特殊的建構函式,1 無參建構函式,2 拷貝建構函式。它們的特殊之處在於 1 當類中沒有定義任何建構函式時,編譯器會預設提供乙個無參建構函式且其函式體為空 2 當類中沒有定義拷貝建構函式時,編譯器會預設提供乙個拷貝建構函式,進行成員變數之間的拷貝。這個拷貝操作是淺拷貝 這裡只講拷貝建構...
結構體的深度拷貝和淺拷貝
具體 和注釋 define crt secure no warnings include include include typedef struct teacher teacher 編譯器的 號操作,只會把指標變數的值,從from copy 到 to,但 不會 把指標變數 所指 的 記憶體空間 給...