为什么清除传递的表在函数范围内不起作用?

时间:2013-03-22 22:21:29

标签: function lua scope lua-table

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

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

2 个答案:

答案 0 :(得分:3)

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

如果你这样做

table1 = { "a" }
table1 = {}

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

当您致电cleartest时,x 指向与{ "a" }相同的值table1,但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会产生相同的结果。

答案 1 :(得分:1)

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

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

在第二种情况下,您将覆盖函数本地的x变量,因此稍后对table1的引用不受影响。请注意,如果您在table1 = {}函数中说过cleartest(),那么它的行为就像第一种情况一样。

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

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