为什么我们不能像这样直观地复制 Lua 中的表:
a = {
a = {},
b = {},
}
b = {}
b = a.b
Run Code Online (Sandbox Code Playgroud)
我在执行此操作时遇到了一些奇怪的错误。如果我使用如下所示的表克隆函数,它会正常工作,我只是不明白为什么首先需要使用克隆函数/最佳实践。
很难描述我在尝试执行第一种方法时遇到的错误,但基本上,如果我尝试在 的a.b部分中添加其他键值b = a.b,那么附加键值并不总是成为我设置的内容他们到。
function deepCopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
Run Code Online (Sandbox Code Playgroud)
然后执行以下操作可以消除任何错误
b = deepCopy(a.b)
Run Code Online (Sandbox Code Playgroud)
在Lua中,表就是一个值,每个不同的表都有一个不同的值。表的值用于标识其内容,但表的内容在概念上并不是表的值。也就是说,要访问表的内容,您需要表的值,但表的值与其内容不同。
表的值可以存储在任何变量中。同样,该值用于标识该表并访问该表的内容,但这与逻辑上作为表内容的值不同。
考虑以下:
tbl1 = { 1, 2, 3 }
tbl2 = tbl1
tbl3 = { 1, 2, 3 }
Run Code Online (Sandbox Code Playgroud)
tbl1和的值tbl2相同;这意味着它们都引用同一个表,因此您可以通过任一变量访问该表的内容。所以tbl1[2]不要tbl2[2]简单地返回 2;他们都访问同一张表。
tbl3与不是同一个表tbl1。它们可能具有逻辑上相同的内容,但对于Lua而言,它们是不同的表。操作存储在 中的表的内容tbl3不会影响任何查看存储在tbl1或中的表的人tbl2。
那么,为什么将表存储到变量中不会复制表的内容呢?几个原因。
深拷贝很昂贵。如果所有副本都很深,您甚至无法return {1, 2, 3}在不执行副本的情况下执行简单的操作。毫无意义的副本,因为没有其他变量可以与该表对话(因为它是就地创建的)。为什么浪费性能?将表作为参数传递给函数或任何其他事物也是如此。
仅深复制可以防止有用的事情,例如从不同位置访问同一个表。如果每个表副本都很深,那么怎么可能有像模块表的本地副本这样简单的东西呢?您不能让表“成员函数”返回对象内部的表,因此您可以使用它来操作该对象中的数据,因为该返回必须复制表。因此,表对象只能通过直接成员函数可变。
深度复制是一个有用的工具。但这不是默认设置,因为它不应该是默认设置。大多数复制表的情况不需要它,用户需要一种从多个位置访问表的方法。
深度复制也没有标准的函数或机制。原因很简单:进行深度复制的方法有很多种,从简单到复杂。例如,您的简单deepCopy函数会破坏(递归地)存储自身的表:
me = { a = 4, other = {} }
me.other.me = me
Run Code Online (Sandbox Code Playgroud)
这是 100% 有效的,你的deepCopy函数将会中断。有一些方法可以实现deepCopy它来处理这个问题,但它们很复杂且昂贵。大多数用户不需要deepCopy可以处理递归对象的。
如果 Lua 的标准库有一个深度复制函数,那么它要么会处理所有这样的情况(因此成本高昂),要么会是一个更简单的函数,可能会在任意数量的极端情况下崩溃(在桌子等)。
因此,最好让深拷贝的任何潜在用户坐下来,准确决定他们想要处理哪些情况,不处理哪些情况。
| 归档时间: |
|
| 查看次数: |
642 次 |
| 最近记录: |