深拷贝和浅拷贝详解

深拷贝和浅拷贝 


      用一句简单的话来说就是浅拷贝,只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。


下面看copymutableCopy


   copymutableCopy。这两个方法都是返回一个id类型的对象,那么这两者之间有什么区别呢?根据官方文档解释,copy方法,返回copyWithZone方法返回的对象(Returns the object returned by copyWithZone:)。而mutableCopy方法,返回mutableCopyWithZone方法返回的对象(Returns the object returned by mutableCopyWithZone:)。简单理解就是调用copy就是调用copyWithZone,调用mutableCopy就是调用mutableCopyWithZone。那么有什么区别呢?

 

 mutableCopy:mutableCopy,使用它copy出来的对象是可以对其内容进行改变的。

 copycopy,使用它复制出来的对象,其内容是不可以改变的。

 

 MutableCopy:可变拷贝,其拷贝过程就是在内存中重新开辟一块区域,将对象复制一份放到这个区域。新对象是可以改变的,而且新对象的改变对源对象是没有影响的。

 copy:不可变copy,同样也是要开辟一段内存空间给新对象,但新对象是不可以改变的。(特殊情况:不可变->不可变的拷贝,是不创建新内存空间的)

(注:这里的可变copy和不可变copy是相对Foundation框架的类而言的,如果我们自己定义的类实现copy,都是可变的)。

 

接下来我们以NSString为例子,来说明copymutableCopy的区别。

-(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 *age=@"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中并不是所有的对象都支持copymutableCopy,遵守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
     */
}

相关文章:

http://www.cocoachina.com/ios/20151202/14520.html

你可能感兴趣的:(深拷贝和浅拷贝详解)