c - 浅/深拷贝术语是否适用于没有引用的对象?
问题描述
免责声明
这篇文章是关于术语“浅拷贝”和“深拷贝”的正确用法,特别是在谈论复制不包含任何引用的对象时。这个问题并不意味着(也不应该)基于意见,除非关于这个话题确实没有达成共识。我已将此问题标记为 C,但它可能与语言无关,除非这些术语在该上下文中的含义已针对特定语言明确定义,但不适用于其他语言。
前言
在复制带有引用的对象时,通常使用术语“浅拷贝”和“深拷贝”,以指定副本是否完整(独立于原始副本)。
但是,我也看到在复制没有引用的对象时使用了这个术语,这两个术语的含义完全相同,无需区分。到目前为止,我还没有找到一个简洁的定义来涵盖这些术语的这种特殊用途。
Stack Overflow 上给出的定义(在标签shallow-copy和deep-copy 中):
浅拷贝包含指向原始变量的链接(内存中的地址)。浅拷贝上的更改会反映在源对象上。
深拷贝复制指向的对象或变量,以便目标(分配给的对象)接收其自己的本地副本。
根据这些定义,没有引用的对象副本将是深层副本。
维基百科上给出的定义(在文章对象复制中):
复制对象的一种方法是浅拷贝。在这种情况下,将创建一个新对象 B,并将 A 的字段值复制到 B。这也称为逐字段复制、逐字段复制或字段复制。如果字段值是对对象的引用(例如,内存地址),则它复制该引用,因此引用与 A 相同的对象,如果字段值是原始类型,则复制原始类型的值。在没有原始类型的语言中(一切都是对象),副本 B 的所有字段都是对与原始 A 的字段相同的对象的引用。因此,引用的对象是共享的,因此如果修改了这些对象之一(来自 A或 B),更改在另一个中可见。浅拷贝很简单而且通常很便宜,因为它们通常可以通过简单地精确复制位来实现。
另一种方法是深拷贝,这意味着字段被取消引用:不是对正在复制的对象的引用,而是为任何被引用的对象创建新的副本对象,并将对这些对象的引用放在 B 中。结果与浅拷贝给出的结果不同因为副本 B 引用的对象与 A 引用的对象不同,并且是独立的。由于需要创建额外的对象,深拷贝更昂贵,并且由于引用可能形成复杂的图,因此可能更加复杂。
根据这些定义,没有引用的对象副本将是浅副本。
我认为这两个术语都不合适,因为“浅拷贝”意味着拷贝不完整,而“深拷贝”意味着拷贝需要某种特殊处理(或高成本)。由于复制没有引用的对象既完整又不需要任何特殊处理,我认为这些术语都不应该使用。然而,这篇文章不是关于我的想法,而是编程社区当前的共识(如果有的话)是什么。
问题
当我复制没有引用的对象时,是否会考虑
- 浅拷贝(因为不涉及引用)?
- 深拷贝(因为目标对象独立于源对象)?
- 两个都?
- 两者都不?
部分深拷贝是否有一个好的术语,其中一些字段是浅拷贝的,而另一些是深拷贝的?
解决方案
当区别不适用时,只需将其称为“副本”。它不是浅拷贝,因为没有共享引用,也不是深拷贝,因为除了结构中的值之外什么都没有被复制。
这个问题就像问岩石是否是无神论者。当然,他们不是有神论者。但是有神论者/无神论者的区别真的适用于他们吗?有些秤只设计用于测量某些事物。
推荐阅读
- php - 在 mongoDB 中 insertMany() 时添加时间戳
- blockchain - 如何在corda中引发拒绝状态攻击?
- python - 在 OR Tools pywrapcp 中遇到 DLL 错误
- docker - Docker, sbt - 无法使用 centos docker 映像安装 sbt
- t4 - 编写基本类定义的 T4 模板
- c# - 替代 httpContext.Request.Path.StartsWithSegments 一次检查多个路径段
- typescript - 有没有办法输入 TypeScript 方法装饰器来限制它可以装饰的方法的类型?
- java - 如果 Java 的分代垃圾收集器遍历活动对象图,它们如何知道要在哪些对象上调用 finalize()?
- python - 生成一个从 1 开始递增到年底的数字,然后在下一年重复
- python-3.x - 我想将我的字典键与 2d 列表的值进行比较,如果该值正确,我想追加到一个新列表