最近被问到一个问题,什么是lua表的弱引用,之前看过lua程序设计第四版,但是当时不记得了,并不能回答出来。之后做了简单查阅,作此记录。
lua的垃圾回收机制是,当一个变量不再被引用了。当触发垃圾回收机制的时候,会回收这部分内存。而弱引用,则是更好的回收内存的一种方法。下面上代码:
对key设置弱引用之前:
1 2 3 4 5 6 7 8 9 10 11
| local t = {} local key1 = { name = 'key1' } t[key1] = 1 key1 = nil
for k,v in pairs(t) do print(k,v) for k1,v1 in pairs(k) do --由于k是一个table,再次打印 print(k1,v1) end end
|
输出结果是这样的:

可以看到,即使我们的表key1置为空了,但是表t依然能够打印出来(是表 t 还是包含着对表 key1 的引用)。下面我们设置key的弱引用,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| local t = {} local key1 = { name = 'key1' } t[key1] = 1 key1 = nil setmetatable(t, {__mode = "k"}) --设置 table 中 key 的弱引用 collectgarbage() --手动触发垃圾回收
for k,v in pairs(t) do print(k,v) for k1,v1 in pairs(k) do print(k1,v1) end end
|
输出结果是这样的:

可以看到,当触发垃圾回收的时候,表t 已经被清空了。这就是由于对 table key 的弱引用,当key值没有被别的值引用时,垃圾回收会直接回收含有这个指定key的表的内存。
** 弱引用也可以设置位 table 的 value**。
** 对value设置弱引用之前:**
1 2 3 4 5 6 7 8 9 10 11
| local t = {} local key2 = { name = 'key2'} table.insert(t, key2) key2 = nil
for k,v in pairs(t) do print(k,v) for k1,v1 in pairs(v) do --由于 v 是一个table 再次打印 print(k1,v1) end end
|
结果如下:

** 对value设置弱引用:**
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| local t = {} local key2 = { name = 'key2'} table.insert(t, key2) key2 = nil
setmetatable(t, {__mode = "v"}) --设置 table value的弱引用 collectgarbage() --手动触发垃圾回收
for k,v in pairs(t) do print(k,v) for k1,v1 in pairs(v) do print(k1,v1) end end
|
结果如下:

也可以同时设置对 key 和 value 的弱引用。这样一旦有一个被置为nil,则垃圾回收时直接触发回收。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| local t = {} local key2 = { name = 'key2'} table.insert(t, key2) key2 = nil
setmetatable(t, {__mode = "v"}) --设置 table,key 和 value 的弱引用 collectgarbage() --手动触发垃圾回收
for k,v in pairs(t) do print(k,v) for k1,v1 in pairs(v) do print(k1,v1) end end
|
** 结果如下:**

** **最后,合理的使用弱引用,可以加强垃圾回收。但是如果不熟悉,也可能造成意想不到的后果。