Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua 为什么将一个表作为值分配给另一个表会导致问题?_Lua - Fatal编程技术网

Lua 为什么将一个表作为值分配给另一个表会导致问题?

Lua 为什么将一个表作为值分配给另一个表会导致问题?,lua,Lua,为什么我们不能像这样在Lua中直观地复制表: a = { a = {}, b = {}, } b = {} b = a.b 我遇到了一些奇怪的虫子在做这件事。如果我像下面这样使用表克隆函数,它会工作得很好,我只是不明白为什么首先需要使用克隆函数/最佳实践 很难描述我在尝试使用第一种方法时遇到的错误,但基本上,如果我尝试在b=a.b的a.b部分中添加额外的键值,那么额外的键值并不总是成为我设置的值 function deepCopy(object) local lookup_

为什么我们不能像这样在Lua中直观地复制表:

a = {
  a = {},
  b = {},
}

b = {}
b = a.b

我遇到了一些奇怪的虫子在做这件事。如果我像下面这样使用表克隆函数,它会工作得很好,我只是不明白为什么首先需要使用克隆函数/最佳实践

很难描述我在尝试使用第一种方法时遇到的错误,但基本上,如果我尝试在
b=a.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
然后执行以下操作将删除所有bug

b = deepCopy(a.b)
  • 变量包含引用,而不是整个表
  • 复制一个引用比复制整个表要高效得多
  • 函数调用有效地将参数分配给该函数的参数,因此,如果分配是完整的,则不可能编写修改表的函数
  • 通常,当我们将一个表分配给某个对象时,我们要么(a)不打算修改该表,要么(b)明确打算使用至少一个变量来修改基础表。请参见前面关于函数的一点。这意味着默认情况下进行完整复制将是一种资源浪费
我的建议是只在您真正需要的时候复制表,如果您确实需要深度复制,则更喜欢浅层复制。事实上,当我需要复制表时,我通常会编写一个专门的复制函数,这样我就不会复制超出我需要的任何内容。

  • 变量包含引用,而不是整个表
  • 复制一个引用比复制整个表要高效得多
  • 函数调用有效地将参数分配给该函数的参数,因此,如果分配是完整的,则不可能编写修改表的函数
  • 通常,当我们将一个表分配给某个对象时,我们要么(a)不打算修改该表,要么(b)明确打算使用至少一个变量来修改基础表。请参见前面关于函数的一点。这意味着默认情况下进行完整复制将是一种资源浪费

我的建议是只在您真正需要的时候复制表,如果您确实需要深度复制,则更喜欢浅层复制。事实上,当我需要复制表时,我通常会编写一个专门的复制函数,这样我就不会复制任何超出我需要的内容。

在Lua中,表是一个值,每个不同的表都有一个不同的值。表的值用于标识其内容,但表的内容在概念上不是表的值。也就是说,要访问表的内容,需要表的值,但表的值与其内容不同

表的值可以存储在任何变量中。同样,该值用于标识该表并访问该表的内容,但这与逻辑上作为该表内容的值不同

考虑以下几点:

tbl1 = { 1, 2, 3 }
tbl2 = tbl1
tbl3 = { 1, 2, 3 }
tbl1
tbl2
的值相同;这意味着它们都引用同一个表,因此您可以通过任一变量访问该表的内容。所以
tbl1[2]
tbl2[2]
不要简单地返回2;它们都访问同一个表

tbl3
tbl1
不同。它们可能有逻辑上相同的内容,但就Lua而言,它们是不同的表。操作
tbl3
中存储的表的内容不会影响查看
tbl1
tbl2
中存储的表的任何人

那么,为什么将表存储到变量中不会复制表的内容呢?有几个原因

  • 深度拷贝很昂贵。如果所有副本都是深层的,那么在不执行副本的情况下,您甚至无法执行简单的
    返回{1,2,3}
    。一个无意义的副本,因为没有其他变量可以与该表对话(因为它是在原位创建的)。为什么要浪费性能?将表作为参数传递给函数或任何其他对象也是如此

  • 深度复制只会阻止从不同位置访问同一个表等有用的操作。如果每个表副本都很深,那么您怎么能拥有像模块表的本地副本这样简单的东西呢?不能让表“成员函数”返回对象内部的表,因此可以使用来操作该对象中的数据,因为该返回必须复制表。因此,表对象只能通过直接成员函数进行修改

  • 深度复制是一个有用的工具。但它不是默认值,因为它不应该是默认值。大多数复制表的情况都不需要它,用户需要一种从多个位置访问表的方法

    深度复制也没有标准的功能或机制。原因很简单:有很多方法可以进行深度复制,从简单到复杂。例如,您的简单
    deepCopy
    函数在一个表上中断,该表存储(递归)自身:

    这是100%有效的,您的
    deepCopy
    功能将在其上中断。有一些方法可以实现
    deepCopy
    ,这样它就可以处理这个问题,但它们既复杂又昂贵。大多数用户不需要能够处理递归对象的
    deepCopy

    如果Lua的标准库有一个深度复制功能,那么它要么可以处理每一个这样的情况(因此成本很高),要么可以是一个更简单的库,可以处理任意数量的角情况(在一个表中有多个对同一个表的引用,等等)


    因此,最好让深度副本的任何潜在用户坐下来,确切地决定他们想要处理哪些情况,哪些情况不需要处理。

    在Lua中,表是一个值,每个不同的表都有一个不同的值。表的值用于标识
    me = { a = 4, other = {} }
    me.other.me = me