3

我想从表中“解开”一个元表,并想知道是否:

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

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

此外,如果元表从来没有引用并且是匿名的,这是否足以破坏附加到表的元表?:

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

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

4

1 回答 1

8

根据 Lua 参考资料,您应该在此处提出问题之前始终查阅该参考资料,除非 tbl 的原始元表受到保护,否则setmetatable(tbl, nil)它将删除 table的元表。tbl或者我们最好说它不会删除元表,而是删除对它的引用。只要有其他引用,作为元表的表当然不会被删除。

在你问人们一个简单的函数调用是否有效之前,请自己尝试一下。您可以使用https://www.lua.org/cgi-bin/demo或任何其他 Lua 解释器,您可以在几秒钟内得到答案,而无需涉及其他任何人。

运行此代码:

setmetatable({}, false)

或者

setmetatable({})

将导致

输入:1:“setmetatable”的错误参数 #2(预期为零或表)

现在您知道您不能输入 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是对该表的最后一次引用,它将在某个时候作为垃圾收集。然后,当然对您设置为元表的表的唯一引用也将消失,它也将被删除。

如果你这样做:

local a = {}
local b = setmetatable({}, a)

, a = nil不会删除 b 的元表

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

于 2016-09-09T12:36:43.210 回答