Lua教程之弱引用table

 更新时间:2014年09月16日 11:33:10   作者:笨木头  
这篇文章主要介绍了Lua教程之弱引用table,本文讲解了自动内存管理的缺陷、弱引用table、三种形式的弱引用等内容,需要的朋友可以参考下

这次要介绍的内容比较少,就一个——弱引用table

1.无法超越人类智慧的智能——自动内存管理的缺陷

我们都知道,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;
  
    -- 强制进行一次垃圾收集
    collectgarbage();
  
    for key, value in pairs(t) do
        print(key.name .. ":" .. value);
    end

这段代码有点复杂,智商低于250的可能会看不懂。

首先以一个table,叫做t。

然后创建一个新的table——key1,这个key1作为t的key值,给t新增了一个字段,赋值为1。

同样的,key2也作为t的一个key值。

接着,调用了collectgarbage函数,可以不管它,我们只要知道,它会让lua进行一次垃圾回收。

最后输出t的所有字段,输出结果如下:

复制代码 代码如下:

[LUA-print] key1:1
[LUA-print] key2:1

这很符合常理,也在我们的预计当中,虽然我们在给t赋值之后,key1和key2都赋值为nil了。

但是,已经添加到table中的key值是不会因此而被当做垃圾的。

换句话说,key1本身已经是nil值,但它曾经所指向的内容依然存放在t中。key2也是一样的情况。

所以我们最后还是能输出key1和key2的name字段。

2.颠覆你的认知——弱引用table

刚刚举例的只是正常情况,那么,如果我们把某个table作为另一个table的key值后,希望当table设为nil值时,另一个table的那一条字段也被删除。

应该如何实现?

这时候就要用到弱引用table了,弱引用table的实现也是利用了元表。

我们来看看下面的代码,和之前几乎一样,只是加了一句代码:

复制代码 代码如下:

 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;
  
    -- 强制进行一次垃圾收集
    collectgarbage();
  
    for key, value in pairs(t) do
        print(key.name .. ":" .. value);
    end

留意,在t被创建后,立刻给它设置了元表,元表里有一个__mode字段,赋值为”k”字符串。

如果这个时候大家运行代码,会发现什么都没有输出,因为,t的所有字段都不存在了。

这就是弱引用table的其中一种,给table添加__mode元方法,如果这个元方法的值包含了字符串”k”,就代表这个table的key都是弱引用的。

一旦其他地方对于key值的引用取消了(设置为nil),那么,这个table里的这个字段也会被删除。
 
通俗地说,因为t的key被设置为弱引用,所以,执行t[key1] = 1后,t中确实存在这个字段。

随后,又执行了key1 = nil,此时,除了t本身以外,就没有任何地方对key1保持引用,所以t的key1字段也会被删除。

3.三种形式的弱引用

对于弱引用table,其实有三种形式:

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执行垃圾回收的时候,并不一定是立刻生效的。
我们刚刚只是为了测试,而强制执行了垃圾回收。

4.结束

好了,这次的内容比较少,其实书上有蛮多关于弱引用的例子的。

关于Lua的最基础部分,到这里算是结束了。

后面的内容是一些库的介绍,以及更深入的一些内容(C和Lua间调用、自定义类型、线程、内存管理)。

接下来可能会放缓文章更新速度,因为好多库的介绍,不知道有没有必要用文章记录下来。

可能而已~

相关文章

  • Lua入门学习笔记

    Lua入门学习笔记

    这篇文章主要介绍了Lua入门学习笔记,本文适合有一定编程基础的同学,可以依据本文快速入门Lua脚本语言,需要的朋友可以参考下
    2014-10-10
  • Lua中的元表和元方法学习笔记

    Lua中的元表和元方法学习笔记

    这篇文章主要介绍了Lua中的元表和元方法学习笔记,本文主要讲解了getmetatable获取元表、setmetatable修改元表等内容,需要的朋友可以参考下
    2014-12-12
  • Lua脚本语言简介

    Lua脚本语言简介

    这篇文章主要介绍了Lua脚本语言简介,Lua最著名的应用是在暴雪公司的网络游戏WOW中, Lua脚本可以很容易的被C/C++代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用,本文就是对Lua语言的详细介绍,需要的朋友可以参考下
    2014-09-09
  • lua开发中实现MVC框架的简单应用

    lua开发中实现MVC框架的简单应用

    最近的游戏项目中使用了lua脚本来开发,项目中用到了MVC框架,最近有朋友问我怎么弄,在这里简单分享一下思路和一些开发中的技巧。有需要的小伙伴可以参考下。
    2015-04-04
  • 深入解读Lua中迭代器与泛型for的使用

    深入解读Lua中迭代器与泛型for的使用

    在Lua中,迭代器常被写为函数而被调用返回下一个元素,而for循环调用迭代器函数则使得迭代更强强大,下面我们就来深入解读Lua中迭代器与泛型for
    2016-06-06
  • 解析Lua中的全局环境、包、模块组织结构

    解析Lua中的全局环境、包、模块组织结构

    Lua中也拥有和Python世界相似的代码的作用范围和组织方式,下面我们就来简单解析Lua中的全局环境、包、模块组织结构,需要的朋友可以参考下
    2016-06-06
  • 详解Lua中的变量相关知识点

    详解Lua中的变量相关知识点

    这篇文章主要介绍了Lua中的变量相关知识点,是Lua入门中的基础知识,需要的朋友可以参考下
    2015-05-05
  • Mac平台中编译安装Lua运行环境及Hello Lua实例

    Mac平台中编译安装Lua运行环境及Hello Lua实例

    这篇文章主要介绍了Mac平台中编译安装Lua运行环境及Hello Lua实例,本文给出了两种Hello Lua示例,一种是控制台直接输出,通过文件编译输出,需要的朋友可以参考下
    2014-10-10
  • Lua协程(coroutine)程序运行分析

    Lua协程(coroutine)程序运行分析

    这篇文章主要介绍了Lua协程(coroutine)程序运行分析,本文讲解分析了一段lua 协程代码是如何运行的,需要的朋友可以参考下
    2015-05-05
  • Lua语言新手简单入门教程

    Lua语言新手简单入门教程

    这篇文章主要给大家介绍的是关于Lua语言新手入门的简单教程,文中通过示例代码一步步介绍的非常详细,对各位新手们的入门提供了一个很方便的教程,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2018-03-03

最新评论