1、深复制与浅复制的概念


->浅复制(shallow copy)概念
 
在SDK Guides中(搜索copy),官方给出的浅复制概念为:
Copying compound objects, objects such as collection objects that can contain other objects, must also be done with care. As you would expect, using the = operator to perform a copy on these objects results in a duplication of the object reference. In contrast to simple objects like CFString and CFData, the “CreateCopy” functions provided for compound objects such as CFArray and CFSet actually perform a shallow copy. In the case of these objects, a shallow copy means that a new collection object is created, but the contents of the original collection are not duplicated—only the object references are copied to the new container.
 
大致意思就是,在你对组合对象进行拷贝时,你拷贝的源对象指针指向的地址中内容,但是并不拷贝该内容中指针指向的内容;
 
->深复制(deep copy)概念
 
同样的,官方给出的深复制概念为:
When you want to create an entirely new compound object, you must perform a deep copy. A deep copy duplicates the compound object as well as the contents of all of its contained objects.
 
大致意思是,当你想完完全全创建一个新的组合对象时,你必须执行一次深拷贝,也就是说,你在拷贝这个组合对象包含的内容的同时,也必须拷贝该对象里指针指向的内容, 相对于浅拷贝,深拷贝多了一次递归行为,即不断的去拷贝该对象中包含的指针的指向的内容,当然,这个指针也可能是指向某个对象的,这时候就需要把该对象中的内容也一起拷贝。
 
2、深复制与浅复制的对比举例
 
为了加深理解,举个简单的例子,你的电脑中有这样一份文件

我对“资源库”文件夹进行拷贝,浅拷贝的意思就是,我对“资源库”文件创建了一个副本(创建时是空的),并且把其中的文件复制一份放到“资源库 副本”中,然后把其中的文件夹放到“资源库 副本”中,但是这些文件夹里面并没有内容,(我们可以通过这个文件夹找到其中的内容,准确的说是将文件夹的替身放到“资源库 副本”中-复制指针或者叫文件夹对象),这时候改变“资源库”下面文件夹中的内容会影响到“资源库 副本”。如果是深拷贝,就相当于,我创建了一个“资源库”文件夹,然后将其中的内容,包括文件、文件夹以及文件夹下面的所有东西,完完整整的拷贝过去,放在另外一个地方。

3、代码举例
 
-> 首先,我们需要明确,copy 与 mutableCopy 在Xcode中默认的操作方式是,在某个对象A调用该方法时,先开辟一块新的内存空间B,然后取出A指向的内容(如果是指针,仅仅取出指针)放到新开辟的空间B中[注意,仅仅是A指向内容,并不包括A指向的内容中指针指向的内容]拷贝一份放到新开辟的空间中,然后返回一个存有新开辟内存地址的对象给消息接收者。
 
->简单对象的copy与 mutableCopy
 

#pragma mark 演示字符串的拷贝(浅拷贝)

// 只有一种情况是浅拷贝:不可变对象调用copy方法时

// 浅拷贝:指针拷贝,不会产生新的对象。源对象计数器+1。

void stringCopy() {

NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];

NSLog(@"%zi", [string retainCount]);

// copy产生的是不可变副本,由于源对象本身就不可变,所以为了性能着想,copy会直接返回源对象本身

// 源对象计数器会+1

// 在浅拷贝情况下,copy其实就相当于retain

NSString *str = [string copy];

NSLog(@"%zi - %p -%p", [string retainCount],string, str);

[str release];

[string release];

}

#pragma mark 演示字符串的拷贝(深拷贝)

// 深拷贝:内容拷贝,会产生新的对象。新对象计数器置为1,源对象计数器不变。

void stringMutableCopy() {

// string:1

NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];

// 产生了一个新的对象,计数器为1。源对象的计数器不变。

// str:1

// string:1

NSMutableString *str = [string mutableCopy];

//NSLog(@"str:%zi", [str retainCount]);

//NSLog(@"string:%zi", [string retainCount]);

// str和string不是相同对象

// NSLog(@"%i", str == string);

[str appendString:@" abcd"];

NSLog(@"string:%@", string);

NSLog(@"str:%@", str);

// str:0

[str release];

// string:0

[string release];

}

总结, 上面的复制只是非组合对象的拷贝,在拷贝时,按照copy或者MutableCopy的默认操作方式进行,只是在由不可变对象复制到不可变对象时,系统为了节约性能就没有新创建这个不可变对象,其余时候还是都要新开辟内存空间,将源对象指向的内容放到新开辟空间中,只是简单的移动,不会进行多余的操作。
 
->组合对象(compound objects)的copy与 mutableCopy
 

NSMutableString *str1 = [NSMutableString stringWithFormat:@"age = %d", 10];

NSMutableString *str2 = [NSMutableString stringWithFormat:@"age = %d", 10];

NSMutableString *str3 = [NSMutableString stringWithFormat:@"age = %d", 10];

NSArray *array1 = @[str1, str2, str3];

NSArray *array2 = [array1 copy];// 浅复制,仅仅是拷贝array1指向的内存地址存放的内容,此处是取出指针,放到array2中,所以array与array2存放的内容一样(都是指向str1,str2,str3的地址)

NSLog(@"%p - %p - %p",array1[0], array1[1], array1[2]);

NSLog(@"%p - %p - %p",array2[0], array2[1], array2[2]);

个人感觉,理解深复制和浅复制的关键在于抓住复制的主要目的,即产生一个副本对象,在改变源对象或者副本对象时,不会影响另外一个,然后浅复制就是浅层次的复制,只复制表面的东西,深复制就是更深层次的复制,只要与之相关的全部复制过去。

关键是理解清楚指针、指向指针的指针、copy的真正意义,之后再回头看深复制与浅复制,so easy。

shallow copy & deep copy的更多相关文章

  1. Numpy copy & deep copy

    1. '='的赋值方式会带有关联性 >>> import numpy as np >>> a = np.arange(4) >>> b = a & ...

  2. Numpy的学习6-深浅赋值(copy&deep copy)

    # = 的赋值方式会带有关联性 import numpy as np a = np.arange(4) # array([0, 1, 2, 3]) b = a c = a d = b # 改变a的第一 ...

  3. Shallow Copy & Deep Copy in Python list

    今天在写一个小程序的时候用到了2维数组, 顺手就写成了[[0.0]*length]*length, 结果为了这个小错,调试了半个多小时, 其实之前对与浅复制和深复制已经做过学习和总结, 但真正编程用到 ...

  4. Shallow copy and Deep copy

    Shallow copy and Deep copy 第一部分: 一.来自wikipidia的解释: Shallow copy One method of copying an object is t ...

  5. shallow copy 和 deep copy 的示例

    本文属原创,转载请注明出处:http://www.cnblogs.com/robinjava77/p/5481874.html   (Robin) Student package base; impo ...

  6. python deep copy and shallow copy

    Python中对于对象的赋值都是引用,而不是拷贝对象(Assignment statements in Python do not copy objects, they create bindings ...

  7. JavaScript 深拷贝(deep copy)和浅拷贝(shallow copy)

    参考: [进阶4-1期]详细解析赋值.浅拷贝和深拷贝的区别 How to differentiate between deep and shallow copies in JavaScript 在编程 ...

  8. Summary: Deep Copy vs. Shallow Copy vs. Lazy Copy

    Object copy An object copy is an action in computing where a data object has its attributes copied t ...

  9. python中的shallow copy 与 deep copy

    今天在写代码的时候遇到一个奇葩的问题,问题描述如下: 代码中声明了一个list,将list作为参数传入了function1()中,在function1()中对list进行了del()即删除了一个元素. ...

随机推荐

  1. 苹果系统开发中的混合编程(1):Objective-C和C++的相互调用

    首先是OC调用C++的代码.   创建一个Objective-C的项目,并创建c++文件MyCppFile.hpp和MyCppFile.cpp.   把要调用Cpp代码的文件名改成mm后缀名,项目代码 ...

  2. linux 信号列表和基本作用

    我们运行如下命令,可看到Linux支持的信号列表: $ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7 ...

  3. javascript笔记——label包含的自定义按钮选中

    自定义按钮ui样式就是需要有label包含input以及带另外的标签作为新ui的载体,此时触发label的click的时候也会选中按钮,也就是说存在事件捕获,解决这个问题有如下方式 用到了 mouse ...

  4. 死亡之ping(Ping of Death)

    最简单的基于IP的攻击可能要数著名的死亡之ping,这种攻击主要是由于单个包的长度超过了IP协议规范所规定的包长度.产生这样的包很容易,事实上,许多操作系统都提供了称为ping的网络工具.在为Wind ...

  5. 基于 unity ngui 上的滚动加载__UiVirtual

    在游戏里面经常会有背包,好友,对话,这样的列表.当列表的内容多了,如果一打开界面就对所有内容进行实例化,会消耗大量的性能,且会造成UI上的卡顿. 于是便需要,在列表里面只实例化屏幕上可见的item.屏 ...

  6. windowsphone 瀑布流&ui虚拟化

    瀑布流已经有点年代了吧,不过wp上还真是挺少资料的.今天抽空把自己之前搞过的东西写出来,避免大家重复劳动. 一.简单的瀑布流排版加入ui虚拟化. 最近看了 段博琼  ui虚拟化的一篇博文,链接:htt ...

  7. 常用sql时间字符转化

    这边主要用到2个函数  convert()  cast() cast是对数据字符类型的转化,例如: cast(date as datetime)   这样就将date字段转化成为时间类型了 因为常用到 ...

  8. Fedora 20 创建桌面快捷方式

    创建desktop文件 sudo touch /usr/share/applications/sublime.desktop 添加内容 [Desktop Entry] Encoding=UTF-8 N ...

  9. git 的使用(4)-git暂缓区工作区原理和修改删除等命令

    文章转载自:http://blog.csdn.net/think2me/article/details/39056379 博主说未经本人允许,不得转载,那就不贴了,拷贝关键部分作备忘 1. 暂存区是G ...

  10. CMD规范的函数与普通函数间调用

    /* * a.js * 普通的非cmd规范的js文件 */ function fun1(){ console.log("fun1"); //调用seajs模块中的fun1 seaj ...