1. 程式人生 > >深拷貝和淺拷貝詳解

深拷貝和淺拷貝詳解

深拷貝和淺拷貝 

用一句簡單的話來說就是淺拷貝,只是對指標的拷貝,拷貝後兩個指標指向同一個記憶體空間,深拷貝不但對指標進行拷貝,而且對指標指向的內容進行拷貝,經深拷貝後的指標是指向兩個不同地址的指標。

下面看copy和mutableCopy

 copy和mutableCopy。這兩個方法都是返回一個id型別的物件,那麼這兩者之間有什麼區別呢?根據官方文件解釋,copy方法,返回copyWithZone方法返回的物件(Returns the object returned by copyWithZone:)。而mutableCopy方法,返回mutableCopyWithZone方法返回的物件(Returns the object returned by mutableCopyWithZone:)。簡單理解就是呼叫copy就是呼叫copyWithZone,呼叫mutableCopy就是呼叫mutableCopyWithZone。那麼有什麼區別呢?

 mutableCopy:mutableCopy,使用它copy出來的物件是可以對其內容進行改變的。

 copy:copy,使用它複製出來的物件,其內容是不可以改變的。

 MutableCopy:可變拷貝,其拷貝過程就是在記憶體中重新開闢一塊區域,將物件複製一份放到這個區域。新物件是可以改變的,而且新物件的改變對源物件是沒有影響的。

 copy:不可變copy,同樣也是要開闢一段記憶體空間給新物件,但新物件是不可以改變的。(特殊情況:不可變->不可變的拷貝,是不建立新記憶體空間的)

(注:這裡的可變copy和不可變copy是相對Foundation框架的類而言的,如果我們自己定義的類實現copy,都是可變的)。

接下來我們以NSString為例子,來說明copy和mutableCopy的區別。

-(void)testString{

    //1建立一個可變字串
    NSMutableString *name=[NSMutableString stringWithString:@"Jack"];
    NSLog(@"源字串: %p---%@",name,name);// %p 指標,%@ 物件
    
    //可變->可變
    NSMutableString *nameOne=[name mutableCopy];
    [nameOne appendString:@"Long"];
    NSLog(@"可變字串: %p---%@",nameOne,nameOne);
    
    //可變->不可變
    NSString *nameTwo=[name copy];
    //NSMutableString *nameTwo2=[name copy];
    //[nameTwo2 appendString:@"22"]; 對於不可變物件使用可變物件接收並使用相應的方法,執行報錯。
    NSLog(@"不可變字串:%p---%@",nameTwo,nameTwo);
    
    NSLog(@"--------不可變字串部分----------");

    //2建立一個不可變字串
    NSString *
[email protected]
"24"; NSLog(@"源字串:%p---%@",age,age); //不可變->不可變 NSString *anotherAge=[age copy]; NSLog(@"不可變字串: %p---%@",anotherAge,anotherAge); //不可變->可變 NSMutableString *mutableAge=[age mutableCopy]; NSLog(@"可變字串: %p---%@",mutableAge,mutableAge); /* 源字串: 0x7b077620---Jack 可變字串: 0x79e0bb70---JackLong 不可變字串:0x79e04f80---Jack --------不可變字串部分---------- 源字串: 0xaf090---24 不可變字串: 0xaf090---24 可變字串: 0x79e08f30---24 */ 由列印結果可知:對不可變物件複製,copy是指標複製(淺拷貝)和mutableCopy就是物件複製(深拷貝)。如果是對可變物件複製,都是深拷貝,但是copy返回的物件是不可變的。 簡單一點就是, copy : 對於不可變物件是淺拷貝,對於其他物件都是深拷貝。mutablecopy:對於所有的物件都是深拷貝. }

 ios中並不是所有的物件都支援copy,mutableCopy,遵守NSCopying協議的類可以傳送copy訊息,遵守NSMutableCopying協議的類才可以傳送mutableCopy訊息。假如傳送了一個沒有遵守上訴兩協議而傳送 copy或者 mutableCopy,那麼就會發生異常。但是預設的ios類並沒有遵守這兩個協議。如果想自定義一下copy那麼就必須遵守NSCopying,並且實現 copyWithZone:方法,如果想自定義一下mutableCopy那麼就必須遵守NSMutableCopying,並且實現 mutableCopyWithZone:方法。

下面自定義類遵守NSCopying和NSMutableCopying協議。(也可以只遵守其中的一個進行相應的copy操作)

#import <Foundation/Foundation.h>

//注意:自定義物件都是可變的
@interface Person : NSObject<NSCopying,NSMutableCopying>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

@end

#import "Person.h"

@implementation Person

- (id)copyWithZone:(NSZone *)zone
{
    Person *p = [[[self class] allocWithZone:zone] init];
    
    p.name = self.name;
    p.age = self.age;
    
    return p;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"%@ %p : name %@", self.class, self, self.name];
}

-(id)mutableCopyWithZone:(NSZone *)zone{

    Person *p = [[[self class] allocWithZone:zone]init];
    
    p.name = self.name;
    p.age = self.age;
    
    return p;
}

@end

測試自定義Person物件 

-(void)testCustomPersonObject{

    Person *p = [[Person alloc] init];
    p.name = @"Jack";
    
    Person *p1 = [p copy];
    p1.name = @"shi";
    
    //注意:這裡如果沒有NSMutableCopying協議並且實現mutableCopyWithZone方法,那麼不能夠使用mutableCopy進行可變拷貝,因為自定義物件並沒有遵守協議,所以直接執行出錯!如果遵守了NSMutableCopying並且實現了mutableCopyWithZone方法,那麼就ok了!
    Person *p2 = [p mutableCopy];
    p2.name = @"hua";
    
    NSLog(@"Person物件:%@ %@ %@", p, p1,p2);
    NSLog(@"Person指標:%p %p", p, p1);
    
    /*
     Person物件:Person 0x79e6e260 : name Jack Person 0x79e6d500 : name shi Person 0x79e6d510 : name hua
     Person指標:0x79e6e260 0x79e6d500
     */
}


相關文章:

相關推薦

Python 拓展之拷貝拷貝

首先我在這介紹兩個新的小知識,要在下面用到。一個是函式 id() ,另一個是運算子 is。id() 函式就是返回物件的記憶體地址;is 是比較兩個變數的物件引用是否指向同一個物件,在這裡請不要和 == 混了,== 是比較兩個變數的值是否相等。 >>> a = [1,2,3] &

Python 拓展之拷貝拷貝(轉載)

總結: 無拷貝--則為引用 淺拷貝--列表依舊為引用 深拷貝--完全拷貝,列表不在為引用 轉載地址:https://www.cnblogs.com/Rocky0429/p/10088657.html 正式開始 首先我在這介紹兩個新的小知識,要在下面用到。一個是函

Python 拓展之拷貝拷貝

正式開始 首先我在這介紹兩個新的小知識,要在下面用到。一個是函式 id() ,另一個是運算子 is。id() 函式就是返回物件的記憶體地址;is 是比較兩個變數的物件引用是否指向同一個物件,在這裡請不要和 == 混了,== 是比較兩個變數的值是否相等。 >

C++細節 拷貝拷貝(位拷貝

前提 在物件拷貝過程中,如果沒有自定義拷貝建構函式,系統會提供一個預設的拷貝建構函式,預設的拷貝建構函式對於基本型別的成員變數,按位元組複製,對於類型別成員變數,呼叫其相應型別的拷貝建構函式。 閱讀《高質量的c c++程式設計》,第9章有這樣一段話,類似的話在《c++pr

javascript實現引用數據類型的拷貝拷貝

var struct blue name 拷貝 ont javascrip ceo ole 關於引用類型值的詳解,請看另一篇隨筆 https://www.cnblogs.com/jinbang/p/10346584.html 深拷貝和淺拷貝,也就是引用數據類型棧和堆的知

拷貝拷貝

深拷貝和淺拷貝  用一句簡單的話來說就是淺拷貝,只是對指標的拷貝,拷貝後兩個指標指向同一個記憶體空間,深拷貝不但對指標進行拷貝,而且對指標指向的內容進行拷貝,經深拷貝後的指標是指向兩個不同地址的指標。 下面看copy和mutableCopy  copy和muta

js中的拷貝拷貝

所有 object 簡單的 col images new color 其他 java 深復制和淺復制只針對像 Object, Array 這樣的復雜對象的。簡單來說,淺復制只復制一層對象的屬性,而深復制則遞歸復制了所有層級。 深淺拷貝 的主要區別就是:復制的是引用(地址)還

python學習系列--拷貝拷貝

深拷貝 淺拷貝 copy deepcopy概念普通情下,復制一個對象是不會新開辟內存空間的,只是把新的對象名稱指向原有的內存地址,這種操作其實不是算是拷貝,只是新的引用。把新的對象置於新的內存空間中,才是拷貝。在python中,深淺拷貝的區別實際上是拷貝的深度不同。操作常見的‘=’號就是一種拷貝方式。pyth

js 中引用類型 的拷貝 拷貝的區別

而是 query reac cat 避免 string val this 臨時 一、曾經在讀JQ源碼的時候,對深拷貝算是有了一點的理解。我們在項目中是不是經常會遇到這樣的問題呢? 後臺返回一個數組對象(引用類型).次數在頁面渲染中需要對部分數據進行處理 比如:銀行卡6234

談Java中的拷貝拷貝

detail tle pac err @override 復制對象 deep har 間接   淺談Java中的深拷貝和淺拷貝(轉載) 原文鏈接: http://blog.csdn.net/tounaobun/article/details/8491392 假如說你想復制一

js的命名空間 && 單體模式 && 變量拷貝拷貝 && 頁面彈窗設計

但是 界面 ket 模式 utf 針對 col con prop 說在前面:這是我近期開發或者看書遇到的一些點,覺得還是蠻重要的。 一、為你的 JavaScript 對象提供命名空間 <!DOCTYPE html> <html> <head&

拷貝拷貝

深拷貝 淺拷貝 #include <stdio.h> int main(int argc, char *argv[]) { char *p1="123"; char *p2="123"; char *p3="456"; const char *p4="ab

python的復制,拷貝拷貝的區別(轉)

pla bsp space 數據 深拷貝 淺拷貝 deepcopy 拷貝 tro 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是拷貝了這個對象的引用 一般有三種方法, alist=[1,2,

python的拷貝拷貝

內存區域 需要 不可變 python3 復制 deepcopy 原始的 pen -m # 對象賦值 a = 'hello world' b = a print('a:',a,', b:',b) # a: hello world

Python-8 拷貝拷貝

water mark alt img 分享 深拷貝 所有 nag copy 淺拷貝 淺拷貝是對於一個對象的頂層拷貝通俗的理解是:拷貝了引用,並沒有拷貝內容 深拷貝 深拷貝是對於一個對象所有層次的拷貝(遞歸) 進一步理解拷貝 拷貝的其他方式 使用copy模

【轉載】圖解 Python 拷貝拷貝

div 原子 總結 但是 home 後來 idt scrip 需要 作者:田小計劃 出處:http://www.cnblogs.com/wilber2013/ Python中,對象的賦值,拷貝(深/淺拷貝)之間是有差異的,如果使用的時候不註意,就可能產生意外的結果。

對象的拷貝拷貝

height post ++ oid 一份 char log pac clu 在copy一個對象時(用一個對象去初始化另外一個對象),會調用類中的拷貝構造函數。如果我們自己沒有在類裏面寫拷貝構造函數,則C++編譯器會調用默認的拷貝構造函數。 淺拷貝:如果類定義的對象包含

拷貝拷貝的區別

log birt 並且 ace UNC 分享 一個 eof 發生 深拷貝和淺拷貝的區別 深拷貝和淺拷貝最根本的區別在於是否真正獲取一個對象的復制實體,和不是引用。 簡單來說 淺拷貝(shallowCopy)只是增加了一個指針指向已存在的內存地址, 深拷貝(deepCop

python的復制,拷貝拷貝的區別

一個 對象賦值 source 深拷貝 對象的引用 數據 拷貝 也會 方法 寫在前面: python中的.copy()拷貝和[:]拷貝皆為淺拷貝 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是

C++本質:類的賦值運算符=的重載,以及拷貝拷貝

fin 過程 種類 解決 對象的引用 執行 面向 鏈式 alt 關鍵詞:構造函數,淺拷貝,深拷貝,堆棧(stack),堆heap,賦值運算符摘要: 在面向對象程序設計中,對象間的相互拷貝和賦值是經常進行的操作。 如果對象在申明的同時馬上進行的初始化操作,則