美文网首页iOS开发
关于深拷贝、浅拷贝和可变拷贝

关于深拷贝、浅拷贝和可变拷贝

作者: kuai空调 | 来源:发表于2017-03-14 15:23 被阅读33次

    经常在论坛和群里看到有人问拷贝相关的问题,回答的总是五花八门、千奇百怪。如果你对几种拷贝的概念还不是很清晰,这篇文章会有帮助。

    什么是浅拷贝

    在谈论深拷贝、浅拷贝等概念之前,先要清楚什么叫拷贝。拷贝(copy)就是复制。当我们已经有一个对象例如:

    NSString *str = @"abc";
    

    那么我想有一个str2和str的值一样该怎么做呢?最简单的办法就是这样:

    NSString *str2 = str;
    

    实际上,这就是浅拷贝,str和str2的内存地址是一样的。也就是说两个指针指向了同一块内存,因此实际上并没有东西被复制出来,就好比文件的快捷方式,无论一个文件有多少快捷方式,这个文件始终只有一个。那么如果我不想要快捷方式,就想要两个文件呢?

    NSString *str3 = [str copy];
    

    理论上来说,这样会划分新的内存地址,生成新的对象,但是实际打印会发现str和str3的地址是一样的。这是因为OC对NSString做了内存管理的优化,这种值相同的string会直接浅拷贝。这也说明,正常情况下NSString是不需要深拷贝的。

    什么是深拷贝

    那么什么时候需要深拷贝呢?其实深拷贝在开发中经常用到:

    @property (nonatomic, copy) NSString *name;
    

    类似这样的属性项目中肯定多的数不清(当然如果你写成@property (nonatomic, strong) NSString *name;是不对的,你的项目会有可能出现莫名其妙的bug)。见名知意,声明为copy的属性在被赋值的时候实际上是会执行copy方法的,就像这样:

    - (void)setName:(NSString *)name{
        _name = [name copy];
    }
    

    为什么要这么做呢?假如我们就将name声明为strong。NSString有个子类NSMutableString,我们是可以将NSMutableString对象赋值给NSString的,像这样:

    NSMutableString *mutableName = [NSMutableString stringWithString:@"Mike"];
    self.name = mutableName;
    

    然而如果我们在后面的代码中修改了mutableName的值,name的值也会随之改变。这当然是不合理的,NSString的值应该是不变的。而copy的作用就是这个。通过copy方法,创建了一个新的值和mutableName相同的对象,所以mutableName的值改变并不会影响到name。

    什么是可变拷贝mutableCopy

    同样见名知意,就是拷贝出一个可变的对象出来。例如:

    NSMutableString *mutableStr = [@"abc" mutableCopy];
    

    通过对NSString进行mutableCopy而产生了一个NSMutableString。我见过一些人创建mutableString就是这样写的,但是从代码规范和效率的角度讲,这样做是不推荐的。

    copy的妙用

    copy方法除了可以对对象进行深拷贝以外还有个优点就是,相比于重新创建一个对象,copy的效率更高。例如要创建一百个MyClass对象,实例化一个对象然后使用copy方法的效率要比实例化一百次高得多。

    相关文章

      网友评论

        本文标题:关于深拷贝、浅拷贝和可变拷贝

        本文链接:https://www.haomeiwen.com/subject/jgqbbttx.html