gpt4 book ai didi

路亚: copying a table efficiently (deep copy)

转载 作者:行者123 更新时间:2023-12-04 17:53:43 31 4
gpt4 key购买 nike

我尝试高效地制作 lua 表的副本。我编写了以下运行良好的函数 copyTable()(见下文)。但我想我可以使用函数的“按值传递”机制获得更高效的东西。我做了一些测试来探索这个机制:

function nop(x)
return x
end

function noop(x)
x={}
return x
end

function nooop(x)
x[#x+1]=4
return x
end

function copyTable(datatable)
local tblRes={}
if type(datatable)=="table" then
for k,v in pairs(datatable) do tblRes[k]=copyTable(v) end
else
tblRes=datatable
end
return tblRes
end

tab={1,2,3}
print(tab) -->table: 0x1d387e0 tab={1,2,3}
print(nop(tab)) -->table: 0x1d387e0 tab={1,2,3}
print(noop(tab)) -->table: 0x1e76f90 tab={1,2,3}
print(nooop(tab)) -->table: 0x1d387e0 tab={1,2,3,4}
print(tab) -->table: 0x1d387e0 tab={1,2,3,4}
print(copyTable(tab)) -->table: 0x1d388d0

我们可以看到,除了在 noop() 中我尝试对现有的进行彻底修改之外,通过函数(当我只是阅读它或添加东西时)传递对表的引用没有变化。

我读了Bas Bossink以及Michael Anderson的回答在 this Q/A .关于传递或表格作为参数,他们强调了“通过引用传递的参数”和“通过值和表格传递的参数是引用”之间的区别,并举例说明了这种差异。

但这到底是什么意思呢?我们是否有引用的副本,但是这与通过引用有什么区别,因为指向并因此操作的数据仍然是相同的,而不是复制的? noop() 中的机制是否特定于当我们尝试对表影响 nil 时,特定于避免删除表或在哪些情况下触发它(我们可以通过 nooop() 看到,当表被修改) ?

我的问题:传递表的机制究竟是如何工作的?有没有一种方法可以更有效地复制表的数据而无需 copyTable 的负担?

最佳答案

Lua 中的参数传递规则与 C 类似:一切 都是按值传递,但表和用户数据作为指针传递。传递引用的副本在用法上并没有太大区别,但它与通过引用传递完全不同。

例如,您专门提出了这一部分。

function noop(x)
x={}
return x
end
print(noop(tab)) -->table: 0x1e76f90 tab={1, 2, 3}

您正在将新表 [1] 的值赋给变量 x(x 现在拥有一个新的指针值)。您没有改变原始表,tab 变量仍然保存指向原始表的指针值。当您从 noop 返回时,您将传回新表的值,该值是空的。 变量保存值,指针是值,而不是引用。

编辑:

错过了您的其他问题。不,如果你想深拷贝一个表,一个类似于你写的函数是唯一的方法。当表变大时,深拷贝非常慢。为避免性能问题,您可以使用类似“倒带表” 的机制,它会跟踪对它们所做的更改,以便它们可以在以后的时间点撤消(在回溯上下文的递归中非常有用) .或者,如果您只是需要防止用户破坏表内部结构,请编写一个“freezable” trait。

[1] 想象一下,{} 语法是一个构造新表并返回指向新表的指针的函数。

关于路亚: copying a table efficiently (deep copy),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42178768/

31 4 0