【语法算法】
弱表的GC规则就这一行:
setmetatable(cache, { __mode = "v" })
__mode = "v" 表示值的弱引用——GC 扫描时不会把弱表里的值算作活跃对象,如果值没有其他强引用,GC 直接回收,表里的键值对自动消失。今天拆开。
一、强引用、弱引用、GC 三段
弱表的三段。强引用:普通的表赋值 t[k] = v 创建的是强引用——只要 t 存在,v 就不会被 GC 回收,哪怕代码里再也没人用它。弱引用:__mode = "v" 的表里,值不影响 GC 判定——只有键有强引用时值才存活,键没有强引用了键值对自动消失。GC:Lua 的 GC 是增量三色标记——从根对象出发标记所有可达对象——弱表里的值如果只被弱表引用,标记阶段不会标记它,清扫阶段直接回收。三段连起来:弱表玩的是"缓存对象的自动过期"——不需要手动清理,GC 帮你干。
graph TD
A[GC根对象] --> B[全局表]
A --> C[当前栈]
B -->|强引用| D[缓存表 cache]
D -->|弱引用-值| E[对象1]
D -->|弱引用-值| F[对象2]
E -->|无其他引用| G[GC回收]
F -->|有其他引用| H[存活]
二、缓存表的正确写法
local cache = setmetatable({}, { __mode = "v" })
local function getCached(key, factory)
local v = cache[key]
if v == nil then
v = factory()
cache[key] = v
end
return v
end
local tex1 = getCached("fire_tex", function()
return loadTexture("fire.png")
end)
tex1 持有返回值的强引用——只要 tex1 还在作用域里,缓存就不会被 GC 回收——tex1 离开作用域后,如果缓存表也没有其他强引用指向这个值,GC 下次运行时自动回收。
三、弱键和弱值的分界线
__mode 有三种取值:"k" 键弱引用、"v" 值弱引用、"kv" 键值都弱引用。弱键适合"对象属性附加表"——以对象为键、附加数据为值,对象被回收后附加数据自动消失。弱值适合"缓存表"——以字符串为键、缓存对象为值,对象没有其他引用了缓存自动清空。两者的分界线就一句话:谁的生命周期由外部决定就用谁做弱引用。最后一条纪律:弱表里不要存布尔值和数字——GC 不会回收这些基础类型,弱引用对它们无效——弱表里只存表、函数、userdata 这些"真正的对象"。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 控制技能的镜像问题是:锁住了怪,自己是不是也闲着?影锁把这道两难摆上台面:影锁四秒,它动不了、你也动不了——它…
【游戏功能】 打断为什么只有"清读条"一种?震魂偏要反过来——不清招、不断势,打在它读条半途的那一劲顺着招震进腑——中劲十秒…
【游戏功能】 蜂群为什么总是一只一只出?蜂王偏要让它们进化:放一只蜂王出来,杀掉小怪喂它——喂三只升一阶,三阶蜂王的毒刺一秒…
【游戏功能】 技能为什么总是不扣自己的血?血刃偏要反着来:开着血刃的每一刀先扣自己二血、命中回三血——净赚一但要打得中,空刀…
【游戏功能】 bn.t = bn.t - dt ——一行旗面倒计时的代码,撑起了破军旗全部的紧迫感:旗立三秒、圈内加攻三成,…
【游戏功能】 淬毒为什么要一毒到底?淬毒刃偏要一层一层叠:一刀淬一层毒、毒层一秒六地烂,六层封顶之后一刀下去毒伤三十六——叠…