Julia 什么时候更改对象也会更改对象的副本?

Julia 什么时候更改对象也会更改对象的副本?,julia,Julia,我被copy()函数弄糊涂了。据我所知,=是指针式赋值,deepcopy()正在创建一个新的独立副本。然而,我发现copy()不是很“稳定”。请参见以下两个示例: b = [[1,2,3], [4,5,6]]; a = copy(b); b[1][1] = 10; a b 在上面的示例中,a在分配b[1][1] 在第二个示例中: b = [[1,2,3], [4,5,6]]; a = copy(b); b[1] = [10,2,3]; a b b[1]的赋值实际上不会改变a。这真令人困惑

我被
copy()
函数弄糊涂了。据我所知,
=
是指针式赋值,
deepcopy()
正在创建一个新的独立副本。然而,我发现
copy()
不是很“稳定”。请参见以下两个示例:

b = [[1,2,3], [4,5,6]];
a = copy(b);
b[1][1] = 10;
a
b
在上面的示例中,
a
在分配
b[1][1]

在第二个示例中:

b = [[1,2,3], [4,5,6]];

a = copy(b);

b[1] = [10,2,3];
a
b

b[1]
的赋值实际上不会改变
a
。这真令人困惑。有人能简单地解释一下发生了什么事吗?谢谢大家!

copy
craete是一个浅拷贝,因此在您的例子中,对对象的引用是复制的,而不是真实数据。 这是因为您的
b
是向量的
向量
,因此它被存储为:

b = [<reference to the first vector>, <reference to the second vector>]

这是对等号、
copy
deepcopy
函数之间差异的更详细解释,摘自我的“”(2019年4月)书的第2章:

内存和拷贝问题 为了避免复制大量数据,Julia默认情况下只复制对象的内存地址,除非程序员明确请求所谓的“深度”副本或编译器“判断”实际副本更有效

如果不希望复制对象的后续修改应用于原始对象,请使用
copy()
deepcopy()

详情如下:

等号(a=b)

  • 执行名称绑定,即将
    b
    引用的实体(对象)也绑定(分配)到
    a
    标识符(变量名称)
  • 结果是:
    • 如果
      b
      然后重新绑定到某个其他对象,
      a
      将保留对原始对象的引用
    • 如果
      b
      引用的对象发生变异(即它内部发生变化),则
      a
      引用的对象(作为同一对象)也会发生变异
  • 如果
    b
    是不可变的,并且内存很小,在某些情况下,编译器会创建一个新对象并将其绑定到
    a
    ,但是对于用户来说是不可变的,这种差异不会明显
  • 对于许多高级语言,我们不需要明确地担心内存泄漏。垃圾收集器的存在使得不再可访问的对象自动销毁
a=副本(b)

  • 创建对象的新“独立”副本并将其绑定到
    a
    。然而,这个新对象可以通过其内存地址依次引用其他对象。在这种情况下,复制的是它们的内存地址,而不是被引用对象本身
  • 结果是:
    • 如果这些被引用对象(例如 向量)反弹到其他一些对象,新对象被引用 通过
      a
      维护对原始对象的引用
    • 如果这些被引用的对象发生变异,那么(相同的对象)被
      a
      a引用的新对象所引用的对象也会发生变异
a=深度复制(b)

  • 一切都是递归地深度复制的
以下代码片段突出显示了“复制”对象的这三种方法之间的差异:

julia> a = [[[1,2],3],4]
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> b = a
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> c = copy(a)
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> d = deepcopy(a)
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a[2] to an other objects.
# At the same time mutates object a:
julia> a[2] = 40
40
julia> b
2-element Array{Any,1}:
   Any[[1, 2], 3]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a[1][2] and at the same
# time mutates both a and a[1]:
julia> a[1][2] = 30
30
julia> b
2-element Array{Any,1}:
   Any[[1, 2], 30]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 2], 30]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a[1][1][2] and at the same
# time mutates a, a[1] and a[1][1]:
julia> a[1][1][2] = 20
20
julia> b
2-element Array{Any,1}:
   Any[[1, 20], 30]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 20], 30]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a:
julia> a = 5
5
julia> b
2-element Array{Any,1}:
   Any[[1, 20], 30]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 20], 30]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
我们可以使用
==
检查两个对象是否具有相同的值,以及使用
===
检查两个对象是否实际相同(即在位级别检查不可变对象,并检查可变对象的内存地址):

  • 给定
    a=[1,2];b=[1,2]
    a==b
    a==a
    为真,但
    a==b
    为假
  • 给定
    a=(1,2);b=(1,2)所有
    a==b、a==a
    a==b
    均为真

嗨,普泽米斯劳,非常感谢您简洁的回答。这就解决了我的难题!另一个问题:在Julia中将一个对象的“值”分配给另一个对象的最佳实践总是使用
deepcopy()?我需要一个经验法则来做这个手术。是的。当你不想花时间考虑它时,使用
deepcopy
Got。非常感谢你!你好,安东内洛,非常感谢您对该机制的详细解释!我来看看你的书。
julia> a = [[[1,2],3],4]
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> b = a
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> c = copy(a)
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> d = deepcopy(a)
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a[2] to an other objects.
# At the same time mutates object a:
julia> a[2] = 40
40
julia> b
2-element Array{Any,1}:
   Any[[1, 2], 3]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a[1][2] and at the same
# time mutates both a and a[1]:
julia> a[1][2] = 30
30
julia> b
2-element Array{Any,1}:
   Any[[1, 2], 30]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 2], 30]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a[1][1][2] and at the same
# time mutates a, a[1] and a[1][1]:
julia> a[1][1][2] = 20
20
julia> b
2-element Array{Any,1}:
   Any[[1, 20], 30]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 20], 30]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4
# rebinds a:
julia> a = 5
5
julia> b
2-element Array{Any,1}:
   Any[[1, 20], 30]
 40
julia> c
2-element Array{Any,1}:
  Any[[1, 20], 30]
 4
julia> d
2-element Array{Any,1}:
  Any[[1, 2], 3]
 4