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
- 结果是:
- 如果这些被引用对象(例如
向量)反弹到其他一些对象,新对象被引用
通过
维护对原始对象的引用a
- 如果这些被引用的对象发生变异,那么(相同的对象)被
a引用的新对象所引用的对象也会发生变异a
- 如果这些被引用对象(例如
向量)反弹到其他一些对象,新对象被引用
通过
- 一切都是递归地深度复制的
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
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