从 Lua 中的 table 中删除 Metatables

Removing Metatables from a table in Lua

我想 "unhook" 来自 table 的元table 并且想知道是否:

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

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

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

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

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

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

在你问别人一个简单的函数调用是否有效之前,你自己试试看。 您可以使用 https://www.lua.org/cgi-bin/demo 或任何其他 Lua 口译员,您可以在几秒钟内得到答案,而无需其他任何人介入。

运行 此代码:

setmetatable({}, false)

setmetatable({})

将导致

input:1: bad argument #2 to 'setmetatable' (nil or table expected)

现在你知道不能输入false了,必须明确输入nil。

要检查 __metatable 您会在参考手册中阅读的内容,您可以尝试使用此代码

local tbl = setmetatable({}, {__metatable = true})
setmetatable(tbl, nil)

结果如下:

input:2: cannot change a protected metatable

你问题的第二部分:

tbl = nil 不会删除 tbl 引用的 table。它只会删除对它的引用 tbl。

local a = {}
local b = a
b = nil
print(a)

a 仍然是 table。您只删除了其中一个引用。

一旦没有剩余引用,垃圾收集器可能会收集 table。

setmetatable(tbl, {}) 将建立对 table 构造函数 {} 返回的 table 的引用,并将该引用存储在 tbl 的内部某处。

如果 tbl 是对 table 的最后引用,它将在某个时候作为垃圾收集。那么当然,您设置为 metatable 的 table 的唯一引用也将消失,它也会被删除。

如果你这样做:

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

, a = nil不会删除b的metatable

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