Lua ephemeron table
Lua表中的键值对,在键或者值任何一方被回收时,都将从表中移除。
瞬表,特指键为弱引用 值为强引用 的表,它的值是否可达仅 取决于键是否可达。如果瞬表的键仅被其值引用(即不可达,没有外部引用),键值对将被移除。这种设计符合直觉,当键不再可达时,也无法通过键取得值,键值对也不再有存在的意义。
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function test (mode) print ("\n__mode:" .. mode) local x = {} print ("x地址:" , x) local test = setmetatable ({}, {__mode = mode}) test[x] = x print (next (test)) print ("取消x外部引用,并执行垃圾回收" ) x = nil collectgarbage () print (next (test))end load ("test('')" )()load ("test('k')" )()load ("test('v')" )()load ("test('kv')" )()
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 __mode: x地址: table: 00000000006cacc0 table: 00000000006cacc0 table: 00000000006cacc0 取消x外部引用,并执行垃圾回收 table: 00000000006cacc0 table: 00000000006cacc0 __mode:k x地址: table: 00000000006ca900 table: 00000000006ca900 table: 00000000006ca900 取消x外部引用,并执行垃圾回收 nil __mode:v x地址: table: 00000000006ca700 table: 00000000006ca700 table: 00000000006ca700 取消x外部引用,并执行垃圾回收 table: 00000000006ca700 table: 00000000006ca700 __mode:kv x地址: table: 00000000006ca9c0 table: 00000000006ca9c0 table: 00000000006ca9c0 取消x外部引用,并执行垃圾回收 nil
可以看出,当test
键为弱引用时,取消x
外部引用会使test[x]
被垃圾回收,无论值是否为强引用。
通过使用瞬表,可以在值为强引用的同时,由键的可达性决定值的可达性,从而避免循环引用使不可达对象无法被垃圾回收。