在 Lua 中将表及其子表设置为 nil 有啥区别?
Posted
技术标签:
【中文标题】在 Lua 中将表及其子表设置为 nil 有啥区别?【英文标题】:What is the difference with tables and their subtables in setting them to nil in Lua?在 Lua 中将表及其子表设置为 nil 有什么区别? 【发布时间】:2019-08-17 23:56:18 【问题描述】:我知道 Lua 会在内存中保留一个表,只要在代码中的某处仍然存在对它的引用,这意味着您不能通过将表作为参数传递给函数来将它们设置为 nil。但是,我不明白为什么您可以对子表执行此操作。
local a =
a.b =
local function remove( t )
t.b = nil
t = nil
end
remove( a )
print( a and a.b, a )
在将 a 作为参数传递给函数 remove 之后,我将参数及其子表设置为 nil。由于上述原因,我知道这不应该将 a 设置为 nil,但是有人可以告诉我为什么 a.b 可以设置为 nil,即使我的理解,它仍然应该从外部引用它,就像 a 一样。
【问题讨论】:
【参考方案1】:我知道 Lua 会在内存中保留一个表,只要在代码中的某处仍然存在对它的引用,
是的,但这实际上意味着我们不必担心内存管理。我们通常不会考虑何时对表进行垃圾收集,除非我们的内存非常紧张并且必须调整垃圾收集器。对于正常使用,我们可以假设一旦我们失去对它的最后一次引用,表就会从内存中删除。
这意味着您不能通过将表作为参数传递给函数来将它们设置为 nil。
这并不是真正的原因。表和 nil 是两种不同的数据类型,因此您不能从字面上将表设置为 nil。通常我们所说的“将表设置为 nil”的意思是获取引用表的变量或表键,并将该变量/键设置为 nil。这可能是也可能不是我们对该表的最后一个引用。
函数不能设置参数变量的原因是参数(函数的局部变量)和用作参数的变量是两个完全不同的变量。
但是有人可以告诉我为什么 a.b 可以设置为 nil,尽管根据我的理解,它仍然应该从外部引用它,就像使用 a 一样。
不,表a.b
没有外部引用。没有引用该表的局部变量。表键没有变量的作用域。对该表的唯一引用是在表 a
内部,它被语句 t.b = nil
修改。
t.b = nil
语句有效,因为它修改了 表t
,不止一个变量引用该表。 't = nil' 分配给 变量 t
,它基本上与任何其他变量无关。
【讨论】:
很好的解释。 “用作参数的变量”:是的,参数就是表达式。作为变量的表达式是一种特殊情况,但一点也不特殊。调用者被传递了表达式的值。它不会知道价值的来源。【参考方案2】:严格来说,您不是“将a.b
设置为nil
”。描述t.bil = nil
所做工作的准确方式是
“将值nil
与表a
中的键"b"
相关联”
例如,将您写的内容与以下内容进行比较:
local o =
o[1] = "one"
o[2] = "two"
o[3] = "three"
-- o currently looks like
-- KEY | VALUE
-- -----+--------
-- 1 | "one"
-- 2 | "two"
-- 3 | "three"
o[2] = nil
-- o now looks like
-- KEY | VALUE
-- -----+--------
-- 1 | "one"
-- 3 | "three"
这很明显不是“将数字2
设置为零”。这只是修改表o
的内容,不再将键2
与任何值关联。
回顾一下你最初询问的代码:
local alpha =
local beta =
alpha[1] = "one"
alpha[2] = beta
alpha[3] = "three"
-- alpha now looks like
-- KEY | VALUE
-- -----+--------
-- 1 | "one"
-- 2 | <beta>
-- 3 | "three"
alpha[2] = nil
-- alpha now looks like
-- KEY | VALUE
-- -----+--------
-- 1 | "one"
-- 3 | "three"
同样,beta
不会以任何方式被修改,数字2
也不会被修改。只是,2
与值beta
的关联已从表alpha
的内容中删除。
【讨论】:
在您的代码中,local beta = ; alpha[2] = beta; alpha[2] = nil;
这会将对 beta 的引用设置为 nil,但实际上并未将 beta(表)设置为 nil。我明白了。但是,在我的代码中,由于子表 a.b 被分配了 nil 值并且不再可访问,那么它与 nil 不一样并且不会被垃圾收集吗?或者它会保留为表的一部分,但以不可访问的方式,直到它所属的表最终正确设置为 nil?
你的代码就是这样的。 .b
就像 [2]
。
a.b
在您的初始代码中不是表的一些特殊“家”。隐含地创建了一个“局部”变量来保存
,然后将该局部变量放入a
中的键b
中,如图所示。以上是关于在 Lua 中将表及其子表设置为 nil 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章