You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua中未显式赋值时ref表索引值为何自动变更?

Lua 5.4表赋值导致原表意外修改的问题

在Lua 5.4中,将ref表赋值给tab[c]后,修改tab[c]的元素时,原ref表的内容也会被改变。原本预期tab[c] = ref是创建ref表的副本,但实际所有tab[c]都指向同一个ref表,导致修改操作影响了原表。

复现代码

-- Lua v5.4
local tab = {}
local ref = {"car1","%line2%","door3"}
local str = {{"%%line2%%","line"},{"car1","car"}}


for c=1,3 do
    tab[c] = ref
    print("\n----block "..c)
    print("\n--ref table ")
    for h=1,#ref do
        print("ref"..c,ref[h])
    end

    print("\n--replacement")
    for d=1,#tab[c] do
        for i=1,#ref do
            if string.match(tab[c][d],str[1][2]) then
                local repl =string.gsub(tab[c][d],str[1][1],"asdf")
                tab[c][d] = repl
                print("tab"..c.."-"..d,tab[c][d])
            end
        end
    end
    
    print("\n--check")
    for h=1,#tab[c] do
        print("check tab"..c.."-"..h,tab[c][h])
    end
end

运行结果

----block 1

--ref table 
ref1    car1
ref1    %line2%
ref1    door3

--replacement
tab1-2  asdf

--check
check tab1-1    car1
check tab1-2    asdf
check tab1-3    door3

----block 2

--ref table 
ref2    car1
ref2    asdf
ref2    door3

--replacement

--check
check tab2-1    car1
check tab2-2    asdf
check tab2-3    door3

----block 3

--ref table 
ref3    car1
ref3    asdf
ref3    door3

--replacement

--check
check tab3-1    car1
check tab3-2    asdf
check tab3-3    door3
[Finished in 27ms]

问题原因

Lua中的表是引用类型,当执行tab[c] = ref时,并没有复制ref表的内容,只是把ref表的引用地址赋值给了tab[c]。这意味着所有tab[1]、tab[2]、tab[3]都指向同一个内存地址中的ref表,修改其中任意一个子表的元素,都会直接修改原ref表的内容。

解决方案

要实现创建ref表的副本,需要手动编写一个表复制函数,在每次循环时复制ref的所有元素到新表中,再将新表赋值给tab[c]。

修改后的代码

-- Lua v5.4
local tab = {}
local ref = {"car1","%line2%","door3"}
local str = {{"%%line2%%","line"},{"car1","car"}}

-- 表复制函数,复制一维数组表
local function copy_table(src)
    local dst = {}
    for i, v in ipairs(src) do
        dst[i] = v
    end
    return dst
end

for c=1,3 do
    tab[c] = copy_table(ref) -- 复制ref表的内容到新表
    print("\n----block "..c)
    print("\n--ref table ")
    for h=1,#ref do
        print("ref"..c,ref[h])
    end

    print("\n--replacement")
    for d=1,#tab[c] do
        for i=1,#ref do
            if string.match(tab[c][d],str[1][2]) then
                local repl =string.gsub(tab[c][d],str[1][1],"asdf")
                tab[c][d] = repl
                print("tab"..c.."-"..d,tab[c][d])
            end
        end
    end
    
    print("\n--check")
    for h=1,#tab[c] do
        print("check tab"..c.."-"..h,tab[c][h])
    end
end

修改后运行结果

----block 1

--ref table 
ref1    car1
ref1    %line2%
ref1    door3

--replacement
tab1-2  asdf

--check
check tab1-1    car1
check tab1-2    asdf
check tab1-3    door3

----block 2

--ref table 
ref2    car1
ref2    %line2%
ref2    door3

--replacement
tab2-2  asdf

--check
check tab2-1    car1
check tab2-2    asdf
check tab2-3    door3

----block 3

--ref table 
ref3    car1
ref3    %line2%
ref3    door3

--replacement
tab3-2  asdf

--check
check tab3-1    car1
check tab3-2    asdf
check tab3-3    door3
[Finished in 26ms]

可以看到,修改后的代码中,原ref表的内容始终保持不变,每个tab[c]都是独立的副本,修改操作不会互相影响。

内容的提问来源于stack exchange,提问作者Jepamb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 13:40:13