为什么在函数的作用域内清除已传递的表格不起作用?

清空表格的方式如下所示,可以得到预期的行为:

table1 = { "a" }
table1 = {}
print(unpack(table1))        -- 结果会打印一个空行

但是如果你在一个函数内做同样的事情,它不起作用:

table1 = { "a" }

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

cleartest(table1)            -- 结果会打印一个空行
print(unpack(table1))        -- 结果为 "a"

这是什么原因导致的呢?

编辑:阐明传递表格给 Lua 的工作方式。x 不是 table1 的一个本地 "副本",因为它是一个 "值就是引用" 类型,实际上是引用到实际表格的引用。例如:

table1 = { "a" }

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

xisref(table1)
print(unpack(table1))         -- 结果为 "a    b",因此 x 是实际表格的一个引用
点赞
用户582
用户582

你并没有清空表格。你创建了一个新的表格并将其赋值给变量。

在第一种情况下,你重写了 table1 变量,所以后面引用的是你新创建的空表格。

在第二种情况下,你重写了局部函数变量 x,所以后面对 table1 的引用不受影响。需要注意的是,如果你在 cleartest() 函数中写了 table1 = {},它会像第一种情况一样。

如果你真的想清空现有的表格,使其他对同一表格的引用也看到清空的状态,你需要写如下代码:

for k in pairs(x) do
    rawset(x, k, nil)
end
2013-03-22 22:24:58
用户1633117
用户1633117

因为你实际上不能清除一个表格的值——只能是名字。

如果你这样做:

table1 = { "a" }
table1 = {}

你没有将{ "a" }设置为{},但你将table1设置为{}替代先前的值。那个值现在是不可访问的,并最终将通过垃圾回收器清除。

当你调用cleartest时,x也将同样指向table1的值{ "a" },但x是它的另一个(本地)名称。通过执行x = {},你只是使x指向一个新的空表,但这对仍指向{ "a" }table1没有任何影响。

回答你的编辑:

是的,x是指向与table1相同的值的引用。但是,x仍然只是一个本地名称,恰好指向那个值。当你将某些东西分配给x时,本地变量x就指向新的东西,而不会影响它之前指向的值。

试试这个(任何地方,全局或本地,都无所谓):

test1 = { "a" }
test2 = test1
-- 现在打印它们会给出相同的表格
test1 = 5
-- 打印test1会给出5;打印test2仍然会给出表格

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

2013-03-22 22:26:24