之前写过一篇博客专门介绍了weak表:Lua弱引用表-CSDN博客,这两天阅读了《programming in lua》后有了些新的体会,在这里只做一些之前没有了解的补充内容。
定义
Lua 自动进行内存的管理。程序只能创建对象(表,函数等),而没有执行删除对象的函数,相反,Lua会自动删除那些失效的对象。垃圾收集器只能在确认对象失效之后才会进行收集;它是不会知道你对垃圾的定义的。类似于任何在全局变量中声明的对象,都不是 Lua 认为的垃圾,即使你的程序中根本没有用到他们。Lua weak表就是为这而诞生的:
Weak 表是一种用来告诉Lua一个引用不应该防止对象被回收的机制。一个weak引用是指一个不被Lua认为是垃圾的对象的引用。如果一个对象所有的引用指向都是weak,对象将被收集,而那些weak引用将会被删除。Lua通过weak tables来实现weak引用:一个 weak tables 是指所有引用都是weak的table。这意味着,如果一个对象只存在于 weak tables 中,Lua 将会最终将它收集。
表的弱引用性通过其__mode来定义。表有keys和values,所以weak也分key weak和value weak。如若key是weak属性的,则__mode = “k”;如若value是weak属性的,则__mode = “v”;如若两者都是,则__mode = “kv”。如下示例所示:
a = {}setmetatable(a, {__mode = "k"})key = {} -- creates first key a[key] = 1key = {} -- creates second key a[key] = 2collectgarbage() -- forces a garbage collection cycle for k, v in pairs(a) do print(v) end--> 2
记忆函数
上篇博客有讲,这里不作过多介绍,简要概括就是可以维护一个weak table存储数据信息,其他地方需要用到时缓存并返回相应信息,下一次垃圾回收会自动清理在这个weak table外再也没有用到的table里的数据信息。
关联对象属性
其实就是维护一个weak table,以对象为key,返回对象的属性信息作为value。与记忆函数不同的是,记忆函数的value是weak的,而关联对象属性的weak table的key是weak的。
weak table的应用
在书里提到访问table域默认值的方法,都分别用到关联对象属性和记忆函数:
local defaults = {} setmetatable(defaults, {__mode = "k"})local mt = {__index = function (t) return defaults[t] end}function setDefault (t, d)defaults[t] = dsetmetatable(t, mt)endlocal a = {1,2}setDefault(a,4)print(a[3]) --4
local metas = {} setmetatable(metas, {__mode = "v"})function setDefault (t, d)if metas[d] == nil thenmetas[d] = {__index = function () return d end}endsetmetatable(t,metas[d])endlocal a = {1,2}setDefault(a,4)print(a[3]) --4
前者和后者相比,后者更适用于多个table同时有多个相同的默认值的情况,前者更适用于多个不同默认值的情况。但是两者对默认值的垃圾回收均可在原table回收之后进行。