关于复制

深复制vs.浅复制

  • 浅复制:复制中把成员指针变量当成“指针”处理,赋值后两个指针指向相同的内存
  • 深复制:复制中把指针成员变量当成“值”处理,赋值后指针指向对象副本(即两个指针指向的内存不同,但内存中内容相同)

C++中的复制

C++中的指针具有缺陷,无法保证指针指向的空间可用(C++从入门到段错误~~)当指针作为类成员时,应进行恰当的管理,

  1. 指针成员采取常规指针型行为。这样的类具有指针的所有缺陷但无需特殊的复制控制。
  2. 类可以实现所谓的“智能指针”行为。指针所指向的对象是共享的,但类能够防止悬垂指针。
  3. 类采取值型行为。指针所指向的对象是唯一的,由每个类对象独立管理。

tip

  • 为了管理具有指针成员的类,必须定义三个复制控制成员:复制构造函数、赋值操作符和析构函数。这些成员可以定义指针成员的指针型行为或值型行为,也就是决定了复制的时候是深复制还是浅复制

OC的复制

集合的复制

不可变集合

  • copy:指针复制。cpy_arr == ori_arr
  • mutableCopy:对象复制(单层深复制,对集合中的元素进行指针复制)
  • initWithArray:copyItems:YES
    • 当集合元素可变时,对该元素进行对象复制;否则进行指针复制
    • 返回__NSArrayI *
  • arrayWithArray对集合进行对象复制,对集合内元素进行指针复制

可变集合

  • copy:对象复制cpy_arr != ori_arr
  • mutableCopy:对象复制(单层深复制,对集合中的元素进行指针复制)
  • initWithArray:copyItems:YES当元素为可变时,复制该元素,不可变时,不复制
    • 返回__NSArrayI *
    • 当集合元素可变时,对该元素进行对象复制;否则进行指针复制
  • arrayWithArray对集合进行对象复制,对集合内元素进行指针复制 ###非集合对象 参考集合的复制(毕竟对象的实例变量也有可能是指针),主要考虑对象是否可变

tip

  • 对于二维数组,即便使用initWithArray:copyItems:YES,对于数组的元素,也只是进行指针复制,亦即:
    • arr_cpy != arr
    • arr_cpy[i] != arr[i]
    • arr_cpy[i][j] == arr[i][j]
  • 若想完全实现深复制,可通过NSKeyedArchiverNSKeyedUnarchiver实现

Swift中的复制

  • Swift中的字符串,数组,字典类型作为结构体被实现
  • 当他们被赋值给一个新的常量/变量,或者作为实参被传递给函数或方法是,将被复制
  • Swift内部管理所有的副本确保整体性能得到优化

pyhton中的复制

  • 对对象赋值时,进行指针复制
aList=[[1, 2], 3, 4] 
b = a
#id(b) == id(a)
  • 切片,对所指指定的元素进行指针复制。
aList=[[1, 2], 3, 4]
b = aList[:]
#id(b) != id(a)
#id(b[0]) == id(a[0])
  • copy.copy 只拷贝父对象,不会拷贝对象的内部的子对象。
aList=[[1, 2], 3, 4]
b = copy.copy(aList)
#id(b) != id(a)
#id(b[0]) == id(a[0])
  • copy.deepcopy 拷贝对象及其子对象
aList=[[1, 2], 3, 4]
b = copy.copy(aList)
#id(b) != id(a)
#id(b[0]) != id(a[0])

C#中的复制

MemberwiseClone

  • MemberwiseClone 方法创建一个浅表副本
  • 具体来说就是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象

实现完全深复制

  • 借助.Net的序列化和反序列化机制,可以十分简单的深度Clone一个对象。
  • 首先将对象序列化到内存流中,此时对象和对象引用的所用对象的状态都被保存到内存中。.Net的序列化机制会自动处理循环引用的情况。
  • 然后将内存流中的状态信息反序列化到一个新的对象中。
原文地址:https://www.cnblogs.com/rainySue/p/guan-yu-fu-zhi.html