从Lua中的表中删除Metatables

May*_*ron 2 lua garbage metatable

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

tbl = setmetatable(tbl, false) -- or nil
Run Code Online (Sandbox Code Playgroud)

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

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

tbl = setmetatable({}, {__index = something})
-- later on:
tbl = nil
Run Code Online (Sandbox Code Playgroud)

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

Pig*_*let 6

根据Lua引用,你应该总是在这里提出一个问题,除非tbl的原始metatable受到保护,否则setmetatable(tbl, nil)将删除表的元表tbl.或者让我们更好地说它不会删除metatable但是会删除它.只要有其他引用,那么作为metatable的表当然不会被删除.

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

运行此代码:

setmetatable({}, false)
Run Code Online (Sandbox Code Playgroud)

要么

setmetatable({})
Run Code Online (Sandbox Code Playgroud)

会导致

输入:1:错误的参数#2到'setmetatable'(nil或表预期)

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

要查看您在参考手册中读过的__metatable,您可以尝试使用此代码

local tbl = setmetatable({}, {__metatable = true})
setmetatable(tbl, nil)
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

输入:2:无法更改受保护的元表

问题的第二部分:

tbl = nil不会删除tbl引用的表.它只会删除它的引用tbl.

local a = {}
local b = a
b = nil
print(a)
Run Code Online (Sandbox Code Playgroud)

a仍然是一张桌子.您只删除了其中一个引用.

一旦没有引用,垃圾收集器就可以收集表.

setmetatable(tbl, {})将建立对表构造函数返回的表的{}引用,并将该引用存储在其中的某个位置tbl.

如果tbl是该表的最后一个引用,它将在某个时刻被收集为垃圾.当然,对你设置为metatable的表的唯一引用也将消失,它也将被删除.

如果你这样做:

local a = {}
local b = setmetatable({}, a)
Run Code Online (Sandbox Code Playgroud)

, a = nil不会删除b的metatable

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