弱引用表(二)
一个表是否为弱引用表是由其元表中的 __mode字段决定的。当这个字段存在时,其值应为一个字符串:如果这个字符串是"k", 那么这个表的键是弱引用的;如果这个字符串是"v",那么这个表的值是弱引用的;如果这个字符串是"kv",那么这个表的键和值都是弱引用的。
以下是一个简单示例:
a = {}
mt = {__mode = "k"}
setmetatable(a, mt)
key = {}
a[key] = 1
key = {}
a[key] = 2
collectgarbage()
for k, v in pairs(a) do print(v) end
--> 2
在本例中,
key = {}
覆盖了指向第一个键的索引。调用collectgarbage强制垃圾收集器进行一次完整的垃圾收集。由于已经没有了指向第一个键的其他引用,因此Lua语言会回收这个键并从表中删除对应的元素。然而,由于第二个键仍被变量key所引用,因此Lua不会回收它。
需要注意的是,只有对象可以从弱引用表中被移除,而像数字和布尔这样的“值”是不可以回收的,例如,如果我们在表a中插入一个数值类型的键,那么垃圾收集器永远不会回收它。当然,如果在一个值为弱引用的弱引用表中,一个数值类型键相关联的值被回收了,那么整个元素也会从这个弱引用表中被移除。
字符串在这里的表现略有差别。虽然从实现的角度来看,字符串是可以回收的,但字符串又与其他可回收的对象不同。其他的对象,例如表和闭包,都是被显式创建的。然而,从程序员的角度来看,字符串是值而不是对象。所以,字符串就和数值和布尔值一样,对于一个字符串类型的键来说,除非它对应的值被回收,否则是不会从弱引用表中被移除的。