【问题标题】:Strange bug with table in lualua中表格的奇怪错误
【发布时间】:2019-07-04 01:46:13
【问题描述】:

我正在向 lua 中的表添加一个字符串。当我在函数中使用表时,原始表正在被更改。我只是一个初学者,但我认为该功能无法做到这一点,因为它超出了它的范围。我有什么明显的遗漏吗?

local testTable= {}
testTable.name = {}
testTable.name[1] = "Jon"

print(testTable.name[1])

local function testFunc(a)
    a.name[1] = "Bob"
end

local newTable = testTable

testFunc(newTable)

print(testTable.name[1])

我预计输出是:

Jon
Jon

实际输出为:

Jon
Bob

testFunc如何改变testTable?

【问题讨论】:

  • 您将表的引用传递给您的函数
  • 不是您要问的,而是:术语“范围”是指您的代码可以访问的变量。在您的示例中,只有函数testFunc 可以访问变量a,因为作为函数的参数,它在函数代码的范围内,但在它之外不存在。从技术上讲,您的函数还可以直接访问 newTable 和 testTable 变量,因为它们是上值(Lua 对闭包环境的术语)。

标签: lua


【解决方案1】:

你将 testTable 的地址分配给 newTable,所以 testTable 和 newTable 指向同一个表。 如果你想输出是

Jon
Jon

您应该在分配 newTable 时复制该表。 你可以像这个函数一样复制表格:

function table.copy(old)
    local new = {}
    for k, v in pairs(old) do
        new[k] = v
    end
    return new
end

【讨论】:

  • 严格来说,我相信“地址”不是 Lua 概念。表是按引用复制的,所有其他 Lua 变量都是按值复制的。这类似于其他没有指针的语言的行为,如 Javascript 或 PHP。
  • 这里是应对表的参考。 lua-users.org/wiki/CopyTable 值得注意的是,比你建议的副本更深
【解决方案2】:

当我在函数中使用该表时,原始表会被更改。 ...我认为该功能无法做到这一点,因为它超出了它的范围。

局部变量有自己的范围,但表没有。要记住两件事:

  • 变量存储引用,而不是值。 (这只会对可变值产生影响。)
  • 表是可变的,也就是说,它们可以在内部更改。

分解:

local newTable = testTable

在这一行中,您将一个变量分配给另一个变量,因此两个变量都引用同一个表。

我们通过分配表中的索引来改变表,因此testFunc 会改变a(实际上是a.name)所指的任何内容。这很方便,因为它允许我们编写函数来改变我们作为参数传递的表。

如您所料,以下函数什么也不做,因为它将一个新表分配给裸名a(恰好是一个局部变量):

local function doNothing(a)
  a = {name = {'Bob'}}
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 2013-09-05
    • 1970-01-01
    相关资源
    最近更新 更多