从Lua中的表中删除Metatables

时间:2016-09-09 10:46:45

标签: lua garbage metatable

我想"解开"表格中有一个表格,想知道是否:

tbl = setmetatable(tbl, false) -- or nil

这是正确的方法吗?我找不到任何有关如何正确执行此操作的信息。我需要使用赋值运算符吗?

另外,如果metatable从未有过引用并且是匿名的,这是否足以破坏附加到表的元表?:

tbl = setmetatable({}, {__index = something})
-- later on:
tbl = nil

并且垃圾收集器足以删除两个表?

1 个答案:

答案 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

所以是的,如果没有剩下对其中任何一个的其他引用,它将删除两个表。