从 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。
我想 "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。