//自定義類物件實現copy需要遵守copy協議(否則程式崩潰),實現必須實現的協議方法,裡面的程式碼就決定了你的copy是深是淺
 #import <Foundation/Foundation.h>
#import "Student.h" //介面部分
// @interface Student : NSObject//<NSCopying/*copy協議*/,NSCoding/*歸檔協議*/>
//
//@property(nonatomic,copy)NSString *name;
//@property(nonatomic,assign)int Age;
//
//@end int main(int argc, const char * argv[])
{
@autoreleasepool
{
Student *student = [[Student alloc] init];
student.name = @"liuguan";
student.Age = ;
NSLog(@"%@",student);
Student *student1 = [student copy];//深複製
//協議實現方式
/***************************
//如果直接return self,則是淺拷貝,如果使用alloc,則是深拷貝
- (id)copyWithZone:(NSZone *)zone
{
Student *stu = [Student allocWithZone:zone];
// Student *stu = [[[[self class] allocWithZone:zone]init]autorelease];// ARC
// stu.name = self.name;
// stu.Age = self.Age;
stu.name = [self.name copy];
stu.Age = self.Age;
NSLog(@"%p***%p",stu.name,self.name);//0x100002078***0x100002078地址一致(淺copy)
return stu;
}//相當於stu的地址等於self的地址,但是這個地址是新開闢的,所以跟copy接收者就沒關係了
***************************/ //Student *student1 = [student copy];//淺複製 // 協議實現方式
/*************************
//- (id)copyWithZone:(NSZone *)zone
//{
// return self;//直接相等
//}//相當於self的地址直接等於copy接受者的地址
相當於 Student *student1 = student ;
***************************/
student1.name = @"wangxinag";
NSLog(@"%@",student1);
NSLog(@"%@",student);
}
return ;
}

在這裡首先提及的就是定義屬性是用的屬性列表中的copy

@property(nonatomic,copy)NSString *name;

在這裡我定義了一個Person類,此處不再陳述

下面是程式碼

Person *p = [[Person alloc] init];

NSMutableString *s = [[NSMutableString alloc] initWithFormat:@"123"];

p.name = s;   //此時,name的值為@"123"

NSLog(@"**%@",p.name);

[s appendString:@"world"];

NSLog(@"%@",p.name);

NSLog(@"%p---%p",s,p.name);

輸出結果:

**123

123

0x100206e00---0x100206cf0

可以看出可變字串的值賦給了屬性name,但是地址變化了,在第一次輸出123後邊我又對s進行了重新賦值為world,但是並未影響到p.name的值,這也就驗證了地址確實不同了。其實它內部是通過

- (void)setName:(NSMutableString *)name

{

if(_name != name){          //判斷是否需要重新賦值

[_name release];        //釋放舊引用,計數器-1

_name = [name copy];   //重新賦值,使用copy********就是這裡*********

}

}

進行了深複製。因為s是可變陣列,所以copy之後會開闢一個新的地址空間。假如s是不可變陣列,那麼就會進行淺複製

假如把程式碼改成:

Person *p = [[Person alloc] init];

NSString *s = @"123";

p.name = s;   //此時,name的值為@"123"

NSLog(@"%@",p.name);

NSLog(@"%p---%p",s,p.name);

輸出結果:

123

0x100001068---0x100001068

地址是一樣的,說明進行了淺複製

總結:

copy:淺拷貝:不產生新的物件,直接指向原有物件(地址資料相同,雖然指標的名字不同)
    拷貝出的結果是不可變物件,跟其接受型別沒有關係,跟其傳入型別也沒有關係
mutableCopy:深拷貝:產生新的物件,其內容是原有物件的內容,地址變了
    拷貝的結果是可變物件,跟其傳入的型別沒有關係,但是會受其接收型別的影響
copy:被複制著是可變,則為深,否則為淺

NSString *s2 = [s1 copy];//八種情況中(s1:mutableString/String;s2:mutableString/String;copy/mutableCopy),只有s1為不可變和利用copy方法  同時滿足時為淺複製,其餘為深複製

//當使用NSCopy複製一個不可變物件時,其行為是淺複製,其餘情況都是深拷貝
//當使用NSMutablecopy時,是深拷貝

那麼為什麼淺複製地址不變呢?

        當被copy者型別是字串常量時(就是不可變字串),系統會為我們優化,聲明瞭多個字串,
        但是都是常量,且內容相等,那麼系統就只為我們申請一塊空間。
賦值過程:輸入資料→暫存器處理→開闢記憶體→寫入資料。一次深複製,可以得到被複制物件指標,並進行一次賦值操作。