我想"解开"表格中有一个表格,想知道是否:
tbl = setmetatable(tbl, false) -- or nil
这是正确的方法吗?我找不到任何有关如何正确执行此操作的信息。我需要使用赋值运算符吗?
另外,如果metatable从未有过引用并且是匿名的,这是否足以破坏附加到表的元表?:
tbl = setmetatable({}, {__index = something})
-- later on:
tbl = nil
并且垃圾收集器足以删除两个表?
答案 0 :(得分:5)
根据Lua引用,您应该在此处提出问题,setmetatable(tbl, nil)
将删除表tbl
的元表,除非tbl的原始元表受到保护。或者让我们更好地说它不会删除metatable但是会删除它。只要有其他引用,那么作为metatable的表当然不会被删除。
如果简单的函数调用有效,请问人们,自己尝试一下。 您可以使用https://www.lua.org/cgi-bin/demo或任何其他Lua解释器,您可以在几秒钟内得到答案,而无需其他人参与。
运行此代码:
setmetatable({}, false)
或
setmetatable({})
将导致
输入:1:错误的参数#2到'setmetatable'(nil或表预期)
现在你知道你不能输入false,你必须明确输入nil。
要查看您在参考手册中读过的__metatable,您可以尝试使用此代码
local tbl = setmetatable({}, {__metatable = true})
setmetatable(tbl, nil)
这导致以下输出:
输入:2:无法更改受保护的元表
问题的第二部分:
tbl = nil不会删除tbl引用的表。它只会删除它的引用tbl。
local a = {}
local b = a
b = nil
print(a)
a仍然是一张桌子。您只删除了其中一个参考文献。
一旦没有引用,垃圾收集器就可以收集表。
setmetatable(tbl, {})
将建立对表构造函数{}
返回的表的引用,并将该引用存储在tbl
的内容中。
如果tbl
是该表的最后一个引用,它将在某个时刻被收集为垃圾。当然,对你设置为metatable的表的唯一引用也将消失,它也将被删除。
如果您这样做:
local a = {}
local b = setmetatable({}, a)
,
a = nil
不会删除b的metatable
所以是的,如果没有剩下对其中任何一个的其他引用,它将删除两个表。