本文目录一览:
- 1、浅复制和深复制的区别?
- 2、编程里面的深拷贝和浅拷贝各是什么意思,怎么理解这两个?
- 3、什么是深拷贝和浅拷贝
- 4、浅拷贝与深拷贝的区别
- 5、PHP对象的浅复制与深复制的实例详解
- 6、深复制(Deep Copy)、浅复制(Shallow Copy)、copy、mutableCopy
浅复制和深复制的区别?
浅层复制:只复制指向对象的指针,而不复制引用对象本身。
深层复制:复制引用对象本身。
编程里面的深拷贝和浅拷贝各是什么意思,怎么理解这两个?
1、浅拷贝:默认的拷贝就是浅拷贝。 仅仅多了个指针指向原来的空间。
2、深拷贝:自己写的拷贝,自己申请了动态内存空间,用了new 或 malloc 。不但多了指针,而且多了空间。
3、用深拷贝的话,最好用自己写的析构,记得在里面释放内存,也可以用默认析构。
4.用浅拷贝(即默认隐藏的拷贝),最好用默认析构,若用自己写的析构里面 ,记得不要释放内存,不然会造成重复释放内存而报错。
什么是深拷贝和浅拷贝
浅拷贝就是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级。
深拷贝和浅拷贝,主要是对象发生复制的时候,根据复制的层级不同来区分的。很多人在这里经常变量赋值发生混淆。对于JavaScript数组等复杂的数据类型来说,将其赋值给其它变量,其实只是复制了对象的地址给它,两个变量指向的是同一个对象,因此普通的赋值既不是深拷贝也不是浅拷贝。
深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:
在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去。
而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。
浅拷贝与深拷贝的区别
数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。
基本数据类型的特点:直接存储在栈(stack)中的数据。
引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里。
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
深拷贝和浅拷贝的示意图大致如下:
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。
我们先来看两个例子,对比赋值与浅拷贝会对原对象带来哪些改变?
上面例子中,obj1是原始数据,obj2是赋值操作得到,而obj3浅拷贝得到。我们可以很清晰看到对原始数据的影响,具体请看下表:
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
修改新对象会改到原对象:
同样修改新对象会改到原对象:
原数组的元素会按照下述规则拷贝:
如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
可能这段话晦涩难懂,我们举个例子,将上面的例子小作修改:
这种方法虽然可以实现数组或对象深拷贝,但不能处理函数。
这是因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数。
该函数库也有提供_.cloneDeep用来做 Deep Copy。
PHP对象的浅复制与深复制的实例详解
PHP对象的浅复制与深复制的实例详解
最近在看原型模式时注意到这个问题~~PHP中对象
'='
与‘clone'的区别
实例代码:
//聚合类
class
ObjA
{
public
$num
=
0;
public
$objB;//包含的对象
function
__construct()
{
$this-objB
=
new
ObjB();
}
//只有实现了下面方法聚合类
才能实现深复制
/*function
__clone()
{
$this-objB
=
clone
$this-objB;
}*/
}
class
ObjB
{
public
$num2
=
0;
}
//原型对象
$objA
=
new
ObjA();
//复制对象(‘='复制引用)
$objA2
=
$objA;
$objA2-num
=
2;
//随着$objA2-num的变化
$objA-num也变化了
print_r($objA-num.'br/');//结果为2
print_r($objA2-num.'br/');//结果为2
//复制对象(‘clone'关键字克隆)
$objA3
=
clone
$objA;
$objA3-num
=
4;
//随着$objA3-num的变化
$objA-num没有变化
print_r($objA-num.'br/');//结果为2
print_r($objA3-num.'br/');//结果为4
//但是clone的对象(是聚合类)中包含其他对象时所包含的对象(objB)复制的是引用
$objA3-objB-num2
=
7;
print_r($objA3-objB-num2.'br/');//结果是7
print_r($objA-objB-num2.'br/');//结果是7/pre
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
深复制(Deep Copy)、浅复制(Shallow Copy)、copy、mutableCopy
1.属性中copy与strong特性的区别
copy:
创建一个对象的副本,在创建的那一刻新对象与原始对象内容相同。
新的对象引用计数为1,与原始对象引用计数无关,且原始对象引用计数不会改变。
使用copy创建的新对象也是 强引用 ,使用完成后需要负责释放该对象。
copy特性可以减少对象对上下文的依赖。新对象、原始对象中任一对象的值改变不会影响另一对象的值。
要想设置该对象的特性为copy,该对象必须遵守NSCopying协议,Foundation类默认实现了NSCopying协议,所以只需要为自定义的类实现该协议即可。
strong:
创建一个强引用的指针,引用对象引用计数加1。
strong特性表示两个对象内存地址相同(建立一个指针,进行指针拷贝),内容会一直保持相同,直到更改一方内存地址,或将其设置为nil。
如果有多个对象同时引用一个属性,任一对象对该属性的修改都会影响其他对象获取的值。
2.浅复制与深复制
对象的拷贝有浅复制和深复制两种方式。浅复制只复制指向对象的指针,并不复制对象本身;深复制是直接复制整个对象到另一块内存中。即浅复制是复制指针,深复制是复制内容。
NSObject提供了copy和mutableCopy 方法,copy复制后对象是不可变对象(immutable),mutableCopy复制后的对象是可变对象(mutable),与原始对象是否可变无关。
深拷贝和浅拷贝最根本的区别:是否真正获取一个 对象的复制实体 ,而不是引用。
浅拷贝:修改堆内存中的同一个值。
深拷贝:修改堆内存中的不同的值。
2.1非集合类对象的copy与mutableCopy
非集合类对象指的是NSString、NSNumber之类的对象,深复制会复制引用对象的内容,而浅复制只复制引用这些对象的指针。因此,如果对象A被浅复制到对象B,对象B和对象A引用的是同一内存地址的实例变量或属性。
2.1.1不可变对象的copy与mutableCopy
2.1.2可变对象的copy与mutableCopy
2.2容器类对象的深复制、浅复制
容器类对象指NSArray、NSDictionary等。
对于容器类,需要探讨的是复制后容器内元素的变化,而非容器本身内存地址是否发生了变化。
2.2.1容器类对象的浅复制
当对集合进行浅复制时,将复制原始集合中元素指针到新的集合,即原始集合中元素引用计数加一。
2.2.2容器类对象的深复制
有两种方式对容器类对象进行深复制:
一:使用initWithArray: copyItems:类型方法,其中,第二个参数为YES。
二:使用归档、解档。
2.3自定义对象的深复制、浅复制
3.修改指针指向
总结:
浅拷贝尽可能少的复制对象,集合的浅拷贝副本只是集合结构的副本,而不是集合内元素的副本。浅拷贝获得的副本与原始集合共享各个元素。
深拷贝复制一切内容。集合的深拷贝会复制集合的结构和元素,但如果集合内元素也是集合,则涉及到一层深拷贝、完全深拷贝。
参考: