【问题标题】:Why does clearing a passed table not work inside the function's scope?为什么清除传递的表在函数范围内不起作用?
【发布时间】:2013-03-12 22:13:26
【问题描述】:

像这样清除表会导致预期的行为:

table1 = { "a" }
table1 = {}
print(unpack(table1))        -- results in printing a blank line

但如果你在函数内部做同样的事情,它不需要:

table1 = { "a" }

function cleartest (x)
    x = {}
    print(unpack(x))
end

cleartest(table1)            -- results in printing a blank line
print(unpack(table1))        -- results in "a"

是什么导致了这种行为?

编辑:阐明 Lua 中的传递表是如何工作的。 x 不是 table1 的本地“副本”,因为它是“值是引用”类型,它实际上是对实际表的引用。例如:

table1 = { "a" }

function xisref (x)
    x[2] = "b"
end

xisref(table1)
print(unpack(table1))         -- results in printing "a    b" thus x is a reference to the actual table

【问题讨论】:

  • 您的编辑表明您似乎对 Lua 中的值和变量的工作方式存在根本性的误解。
  • 请让我知道我的例子不正确的地方。

标签: function lua scope lua-table


【解决方案1】:

因为您实际上无法清除表的值 - 只能清除名称。

如果你这样做了

table1 = { "a" }
table1 = {}

您没有将{ "a" } 设置为{},而是将table1 设置为{} 替换之前的值。该值现在无法访问,最终将被垃圾收集器清除。

当您调用 cleartest 时,x指向与 table1 相同的值 { "a" },但 x 是不同的(本地)名称。通过执行x = {},您只需让x 指向一个新的空表,但这不会改变table1,它仍然指向{ "a" }

回应您的编辑:

是的x 是对与table1 相同值的引用。 但是 x 仍然只是一个恰好指向该值的本地名称。当你给 x 赋值时,局部变量 x 指向新的东西,而不会影响它之前指向的值。

试试这个(在任何地方,全球,本地,没关系):

test1 = { "a" }
test2 = test1
-- printing them now gives the same table
test1 = 5
-- printing test1 gives 5; printing test2 still gives the table

test2 分配新内容并打印test1 将产生相同的结果。

【讨论】:

  • 我明白了。这完全是对作业如何运作的误解。这么简单的事情。非常感谢您的澄清!
【解决方案2】:

你没有清理桌子。您正在创建一个新表并将其分配给变量。

在第一种情况下,您将覆盖 table1 变量,因此后面的引用会获取您的新空表。

在第二种情况下,您将覆盖函数本地的x 变量,因此后面对table1 的引用不受影响。请注意,如果您在 cleartest() 函数中使用了 table1 = {},它的行为将与第一种情况类似。

如果你真的想清除现有的表,这样对同一个表的其他引用看到清除状态,你需要写类似

for k in pairs(x) do
    rawset(x, k, nil)
end

【讨论】:

  • x 变量不是函数的本地变量,它是对实际表的引用。例如,函数内部的 x[2] = "b" 会将 table1 附加到函数范围之外。
  • @RossCharette:你错了。 x 函数本地的。但它也是对实际表格的引用。但这并没有改变对x 的分配实际上不会影响原始表的事实。
  • @RossCharette:如果我有代码local a = { "a" }; local b = a; b = {}; print(unpack(a)),你认为会发生什么?您的问题意味着您认为它不会打印任何内容,但实际上它会打印 a,因为分配给 b 的分配实际上并没有改变 a
  • 对 x 的赋值肯定会改变原始表,请参阅我在上面原始问题中的编辑并自己测试。
  • @RossCharette 没有。 x[2] = "b"不是分配给xx 首先被评估为指向您的值 { "a" } 的名称(与 table1 指向的值相同)。那么[2] = "b" 是一个发生在这个值上的赋值。在函数中尝试x = {"b"}:它不会改变table1,因为这x 的赋值。如果您不相信 Kevin 或我,请阅读参考手册。我用另一个澄清的例子更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 2021-05-29
  • 1970-01-01
相关资源
最近更新 更多