首页 > 技术文章 > [Lua]弱引用table

lyh916 2017-12-09 14:43 原文

参考链接:

http://www.benmutou.com/archives/1808

 

一.强引用table

lua中的table是引用类型,更准确地说,是强引用类型。如下第二段代码,在内存中有一个{name = "123"}的table,并用a和b[1]指向它,然后置空a,此时就只剩下b[1]指向它了。这种引用方式和我们所认知的引用是一样的。值得一提的是,这里的a = nil为什么不等同于{name = "123"} = nil呢,意思是将指向的这个表删掉呢?因为lua是具备自动内存管理的,我们只管创建,删除操作是lua自动进行的,因此这里的a = nil并不是删除表,而是指将a对这张表的引用去掉,当没有地方引用这张表时,这张表就会被lua自动清掉。

1 a = {name = "123"}
2 b = a
3 a.name = "456"
4 print(b.name)--456
1 a = {name = "123"}
2 b = {}
3 b[1] = a
4 a = nil
5 print(b[1].name)--123

 

二.弱引用table

如上所说,一般我们创建的table都是强引用table,即key和value都是强引用,强引用可以防止他们指向的对象被回收。如果一个对象存在强引用,那么它就不会被回收。而相对地,就有弱引用,弱引用不能防止对象被回收。如果一个对象只存在弱引用,那么它就会被回收。lua中通过弱引用table来实现弱引用。弱引用table有三种形式:

1.key值弱引用。设置方法为setmetatable(b, {__mode = "k"})

2.value值弱引用。设置方法为setmetatable(b, {__mode = "v"})

3.key和value值弱引用。设置方法为setmetatable(b, {__mode = "kv"})

当一个key或者value被收集时,整个key以及对应的value都会从table中移除。

如下所示,{name = "123"}这个table存在强应用b[1],所以没被回收。

1 a = {name = "123"}
2 b = {}
3 b[1] = a
4 a = nil
5 collectgarbage()
6 for k,v in pairs(b) do
7     print(k) --1
8     print(v) --table: 0054E430
9 end

下面新增一句代码,表示b的value对其指向的对象的引用是弱引用,而b的key对其指向的对象的引用仍然是强引用(对于table来说,其key和value可以指向任何类型的对象,除了key不能指向nil)。{name = "123"}这个table只存在弱应用b[1],所以被回收。

 1 a = {name = "123"}
 2 b = {}
 3 setmetatable(b, {__mode = "v"}) --add
 4 b[1] = a
 5 a = nil
 6 collectgarbage()
 7 for k,v in pairs(b) do
 8     print(k) --
 9     print(v) --
10 end

 

推荐阅读