关于Lua弱表中瞬表的测试
关于Lua弱表中瞬表的测试
Lua手册中有个关于弱表中瞬表的细节:特别注意,如果表内的一个键仅仅被其值所关联引用,这个键值对将被表内移除
这个情况是用来处理循环引用的,测试如下
-- [[测试1
-- 新建2个对象
local x = {}
local y = {}
-- 使之循环引用
x.refY = y
y.refY = x
-- 打印地址
print("x:", x, "y:", y)
local test = {}
setmetatable(test, { __mode = "k" }) -- 现在test就是一个瞬表(暂时表)
test[x] = y -- 存入对象
print(next(test))
-- 去掉外部引用=> 局部变量不再直接或间接引用对象
x = nil
y = nil
--- 进行垃圾回收
collectgarbage()
print(next(test))
--OutPut:
> x: table: 0000023E67AF7600 y: table: 0000023E67AF7A00
> table: 0000023E67AF7600 table: 0000023E67AF7A00
> nil
由上例测试1可以看出,对于瞬表而言,当外部引用丢失,键只被值索引时,在垃圾回收时,弱引用可以处理循环引用的情况,弱引用被正常回收.
-- [[测试2
-- 新建2个对象
local x = {}
local y = {}
-- 使之循环引用
x.refY = y
y.refY = x
-- 打印地址
print("x:", x, "y:", y)
local test = {}
setmetatable(test, { __mode = "v" }) -- 不是瞬表
test[x] = y -- 存入对象
print(next(test))
-- 去掉外部引用=> 局部变量不再直接或间接引用对象
x = nil
y = nil
--- 进行垃圾回收
collectgarbage()
print(next(test))
--OutPut:
> x: table: 0000023E67AF8140 y: table: 0000023E67AF7480
> table: 0000023E67AF8140 table: 0000023E67AF7480
> table: 0000023E67AF8140 table: 0000023E67AF7480
测试2的代码与测试1除了 __mode='v'
,其他完全相同,由测试2可以看出,如果不是瞬表,在循环引用的情况下,弱引用不会被正常回收.
所以:
属性为弱键强值的表也被称为 暂时表。 对于一张暂时表, 它的值是否可达仅取决于其对应键是否可达。 特别注意,如果表内的一个键仅仅被其值所关联引用, 这个键值对将被表内移除。
PS: 之前在哪儿看到Lua解循环引用的办法,现在忘记了,如果有人看到过能在评论区贴一下就多谢了