为什么要引入弱表?
我们都知道,lua具有自动内存管理,我们只管创建对象,无需删除对象,对于不再需要的对象只需要简单置为nil,
lua会自动删除那些被认为是垃圾的数据;问题就在于,什么对象才是垃圾对象呢?有时候,程序员很清楚的知道某个对象
是垃圾,而lua却无法发现;
比如下面的例子:
t = {
};
-- 使用一个table作为t的key值
key1 = {
name = "key1"};
t[key1] = 1;
key1 = nil;
-- 又使用一个table作为t的key值
key2 = {
name = "key2"};
t[key2] = 1;
key2 = nil;
for key, value in pairs(t) do
print(key.name .. ":" .. value);
end
-- 强制进行一次垃圾收集
collectgarbage();
for key, value in pairs(t) do
print(key.name .. ":" .. value);
end
执行结果如下:
key1:1
key2:1
key1:1
key2:1
代码首先创建了一个空表t,接着创建了一个表key1,然后将key1作为t的键,赋值为1,最后将key1置nil;
key2表也是一样的操作;
接着程序执行了一次collectgarbage()强制进行一次垃圾回收,此时key1和key2表都被置nil,但是并没有被强制回收,
换句话说,虽然key1本身为nil,但是他先前指向的内容并没有被删除,因为这个内容被保存在了t中;
那么,如果我们希望在将key1置为nil时,他指向的内容就被清空,不管t中是否引用了这个内容,该怎么做?
我们来看如下的代码:
t = {
};
-- 给t设置一个元表,增加__mode元方法,赋值为"k"
setmetatable(t, {
__mode = "k"});
-- 使用一个table作为t的key值
key1 = {
name = "key1"};
t[key1] = 1;
key1 = nil;
-- 又使用一个table作为t的key值
key2 = {
name = "key2"};
t[key2] = 1;
key2 = nil;
for key, value in pairs(t) do
print(key.name .. ":" .. value);
end
-- 强制进行一次垃圾收集
collectgarbage();
for key, value in pairs(t) do
print(key.name .. ":" .. value);
end
以上代码在创建了表t后,立即将t设置为元表,元表里面有一个__mode字段,值为"k",通过运行结果,我们知道
在执行collectgarbage()之前,能够输出t中的元素,但是执行垃圾回收之后,就不能再次输出t中的元素的,这是因为
将表设置为元表后,通过__mode = "k"将其指定为对键的弱引用,也就是说,一旦表中的某个键被垃圾回收,t中会删除
这个键对应的元素;
三种形式的弱引用
lua中提供了以下三种形式的弱引用:
(1)key值弱引用,也就是刚刚上面提到的那种形式的弱引用,只要其他地方没有对key值得引用,那么table自身
的这个字段也会被删除,设置方法:setmetatable(t, { __mode = "k"});
(2)value值弱引用,类似的,只要其他地方没有对value值得引用,table的这个value所在的字段也会被删除,
设置方法:setmetatable(t, { __mode = "v"});
(3)key和value弱引用,规则一样,只要key或者value中一个在其他地方没有引用,table中对应的字段就被
删除,设置方法:setmetatable(t, { __mode = "kv"});
为什么要引入弱表?
我们都知道,lua具有自动内存管理,我们只管创建对象,无需删除对象,对于不再需要的对象只需要简单置为nil,
lua会自动删除那些被认为是垃圾的数据;问题就在于,什么对象才是垃圾对象呢?有时候,程序员很清楚的知道某个对象
是垃圾,而lua却无法发现;
比如下面的例子: