Weak表是一种用来告诉Lua一个引用不应该防止对象被回收的机制。
一个weak引用是指一个不被Lua认为是垃圾的对象的引用。
一个对象所有的引用指向都是weak,对象将被收集,而那些weak引用将会被删除。
表的weak性由他的metatable的__mode域来指定的。key和value只要有任何一个被回收,整个key-value都将消失。
a, b = {}, {}
setmetatable(a, b)
b.__mode = "k" -- 表a是一个key为weak引用的weak表
key = {} -- lua不会自动回收全局变量,只能显示的key=nil删除。
a[key] = 1
key = {}
a[key] = 2 -- 被覆盖的key将被回收。也就是第一个key:1键值对将消失。
a[{}] = 1 -- 将别回收
a[1] = 2 -- 数值型的key不会被回收。
a["a"] = 2 -- string型的key不会被回收。
collectgarbage() -- forces a garbage collection cycle
记忆函数
常见的,我们用一个table来缓存数据,但是如果缓存的数据过了段时间在外部没有被使用了(引用),我们可以把这部分缓存给清理掉。weak表的特性就可以很好的满足。
------------------缓存编译的chunk块------------------
local results = {}
setmetatable(results, {__mode = \"v\"})
function mem_loadstring (s)
if results[s] then
return results[s]
else
local res = loadstring(s)
results[s] = res
return res
end
end
------------------缓存RGB色值------------------
local results = {}
setmetatable(results, {__mode = \"v\"}) -- make values weak
function createRGB (r, g, b)
local key = r .. \"-\" .. g .. \"-\" .. b
if results[key] then return results[key]
else
local newcolor = {red = r, green = g, blue = b}
results[key] = newcolor
return newcolor
end
end
带默认值的表
它们都有相似的复杂性和相似的性能。第一种方法需要在每个默认值的tables中添加一些文字(一个默认的入口)。第二种方法需要在每个不同的默认值加入一些文字(一个新的表,一个新的闭包,metas中新增入口)。所以,如果你的程序有数千个tables,而这些表只有很少数带有不同默认值的,第二种方法显然更优秀。另一方面,如果只有很少的tables可以共享相同的默认vaules,那么你还是用第一种方法吧。
-- 一个weak table保存所有对象的默认值,key是弱引用
-- key:对象,value:默认值
--defaults = {
-- [object] = default --object weak
--}
local defaults = {}
setmetatable(defaults, {__mode = \"k\"})
local mt = {__index = function (t) return defaults[t] end}
function setDefault (t, d)
defaults[t] = d
setmetatable(t, mt)
end
--metas = {
-- [default] : metatable --metatable weak
-- }
local metas = {}
setmetatable(metas, {__mode = \"v\"})
function setDefault (t, d)
local mt = metas[d]
if mt == nil then
mt = {__index = function () return d end}
metas[d] = mt -- memoize
end
setmetatable(t, mt)
end