Lua的weak table机制可以实现一些神奇的功能。将一个table设置为weak的方法:
setmetatable( table, <strong><span style="font-size:18px;">{__mode = 'kv'}</span></strong>)
__mode如果含有'k',表示table的key是 弱引用;含有'v'表示value是弱引用。因为lua有GC,当一个object没有被引用的时候就会被kill,对object的弱引用是会被GC忽略的,对GC而言就相当于没有引用。所以弱引用可以对object进行访问,不过一旦这个object不再被其他变量强引用,就会被回收,若引用自动消失了。
实现原理是,GC在遍历所有GCObject时,如果发现是table,就会找他的metatable(mt)。根据mt的__mode变量,GC过程决定要不要顺着table的key、value遍历下去。
一个需要注意的地方是,因为GC不是即时的,所以弱表实际上是提供了一种访问“garbage”的方式,而访问这个垃圾可能会带来问题,甚至让程序崩溃。即使一个object只被若引用了,距离它被回收还有一阵子,甚至几秒钟。
举个例子,通过弱表引用所有的图片资源,目的是进行自动渲染,当图片被释放后,自动不再渲染。可能会在某次渲染的过程中,获取了一个应该被释放但还未被释放的资源,并且进行了检查,该资源还在,完了之后GC启动,将图片释放了,回到用户代码中再去渲染图片时,就会报错说资源不存在,而且十分让人困惑(因为前面有资源合法性检查的代码)。这很像多线程造成的问题。