Julia 0.6.2中push!偶发覆盖先前元素问题求助
解决Julia 0.6.2中
push!导致数组元素被覆盖的问题 我一眼就看出你踩了Julia里引用类型的经典坑!你遇到的问题根本不是push!函数的bug,而是数组的引用特性导致的——你在循环外部定义了entry = zeros(Float64,3),之后每次循环都是修改同一个数组的内容,再把它的引用push!到out里。最终out里的所有元素其实都指向内存中同一个数组对象,所以最后所有条目看起来都和最后一次修改的内容完全一致。
问题根源拆解
在Julia里,数组属于可变引用类型:当你把数组赋值给变量或者push到集合中时,传递的是指向该数组的内存地址,而非创建一个全新的副本。你的循环相当于反复修改同一个数组,然后多次把它的地址塞进out数组里,自然最后所有元素都一模一样。
两种修复方案
方案1:将数组定义移到循环内部
每次循环都创建一个全新的数组对象,从根源上避免引用复用:
using Distributions l = [(0, 10, 1, [1.1; 2.2], [1/3; 2/3], 4)]; out = Array{Float64}[ ]; for i = 1:length(l) # 每次循环创建新的空数组 entry = zeros(Float64,3); row = l[i]; startingtime = row[1]; finishingtime = row[2]; node = row[3]; sizelist = row[4]; sizedistr = row[5]; density = row[6]; t = startingtime; deltat = rand(Exponential(1/density)); # 这里添加你对entry的修改逻辑,比如: entry[1] = t; entry[2] = t + deltat; entry[3] = node; push!(out, entry); end
方案2:push时传入数组副本
如果必须在循环外定义entry,每次push前创建数组的副本,确保out里存储的是独立的数组:
using Distributions l = [(0, 10, 1, [1.1; 2.2], [1/3; 2/3], 4)]; out = Array{Float64}[ ]; entry = zeros(Float64,3); for i = 1:length(l) row = l[i]; startingtime = row[1]; finishingtime = row[2]; node = row[3]; sizelist = row[4]; sizedistr = row[5]; density = row[6]; t = startingtime; deltat = rand(Exponential(1/density)); # 修改原entry数组的内容 entry[1] = t; entry[2] = t + deltat; entry[3] = node; # push副本而非原数组引用 push!(out, copy(entry)); end
额外说明
这个问题并不是Julia 0.6.2特有的,它是引用类型的基本特性——哪怕你升级到Julia 1.x版本,这个逻辑依然适用。只要记住:可变对象(比如数组)传递的是引用,要存储独立实例就必须显式创建副本。
内容的提问来源于stack exchange,提问作者horvill
相关产品推荐
相关产品推荐

