【发布时间】:2020-11-07 10:12:51
【问题描述】:
免责声明
这篇文章是关于“浅拷贝”和“深拷贝”这两个术语的正确用法,特别是在谈到复制一个不包含任何引用的对象时。这个问题并不意味着(也不应该)基于意见,除非关于这个话题确实没有达成共识。我已将此问题标记为 C,但它可能与语言无关,除非这些术语在该上下文中的含义已针对特定语言而非其他语言明确定义。
前言
术语“浅拷贝”和“深拷贝”通常用于复制带有引用的对象,以指定副本是否完整(独立于原始副本) .
但是,我也看到了在复制没有引用的对象时使用的这个术语,其中两个术语的含义完全相同,无需区分。到目前为止,我还没有找到一个简洁的定义来涵盖这些术语的这种特殊用途。
-
Stack Overflow 上给出的定义(在标签shallow-copy 和deep-copy 中):
浅拷贝包含指向原始变量的链接(内存中的地址)。浅拷贝上的更改会反映在源对象上。
深拷贝复制指向的对象或变量,以便目标(被分配的对象)接收自己的本地副本。
根据这些定义,没有引用的对象副本将是深层副本。
-
维基百科上给出的定义(在文章Object copying中):
复制对象的一种方法是浅拷贝。在这种情况下,将创建一个新对象 B,并将 A 的字段值复制到 B。这也称为逐字段复制、逐字段复制或字段复制。如果字段值是对对象的引用(例如,内存地址),它会复制该引用,因此引用与 A 相同的对象,如果字段值是原始类型,它会复制原始类型的值。在没有原始类型的语言中(一切都是对象),副本 B 的所有字段都是对与原始 A 的字段相同的对象的引用。因此,引用的对象是共享的,因此如果修改了这些对象之一(来自 A或 B),更改在另一个中可见。浅拷贝很简单而且通常很便宜,因为它们通常可以通过简单地精确复制位来实现。
另一种方法是深度复制,这意味着取消引用字段:不是复制对对象的引用,而是为任何引用的对象创建新的复制对象,并将对这些对象的引用放在 B 中。结果与结果不同 a浅拷贝给出了副本 B 引用的对象与 A 引用的对象不同,并且是独立的。由于需要创建额外的对象,深拷贝更昂贵,并且由于引用可能形成复杂的图,因此可能会更加复杂。
根据这些定义,没有引用的对象副本将是浅拷贝。
我认为这两个术语都不合适,因为“浅拷贝”意味着拷贝不完整,而“深拷贝”意味着拷贝需要某种特殊处理(或高成本)。 由于复制没有引用的对象既完整又不需要任何特殊处理,我认为这些术语都不应该使用。然而,这篇文章不是关于我的想法,而是编程社区当前的共识(如果有的话)。
问题
当我复制一个没有引用的对象时,会被考虑
- 浅拷贝(因为不涉及引用)?
- 深拷贝(因为目标对象独立于源对象)?
- 两者都有?
- 也没有?
部分深拷贝有什么好的术语,其中一些字段是浅拷贝的,而另一些是深拷贝的?
【问题讨论】:
-
你复制了所有的指针,你也没有复制任何指针,所以两者都是。
-
Wikipedia 上的定义... 你搞错了。维基百科对于提供描述或示例等事情很有用。将其视为权威是一个巨大的错误......
-
该术语不是“简单”或“复杂”对象,相关术语是组合或聚合。您只能执行聚合的深层复制(无论成员是嵌入还是引用),而您可以对组合执行浅层、写入时复制或急切的深层复制。
-
@AndrewHenle,虽然我同意在依赖维基百科时需要有一定的酌处权,但我发现问题中提出的特定引文很好地定义了术语“浅拷贝” ”和“深拷贝”与我对它们的理解一致。我认为这些术语的当前 SO 标签信息具有误导性。
-
注意:我为深拷贝和浅拷贝更新了标签 wiki。希望它们不再与 Wikipedia 文章(深拷贝标签 wiki 已经提到,浅拷贝现在也提到)显示出看似不一致的地方。
标签: c terminology deep-copy shallow-copy