热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

弱引用table《Lua程序设计》

>Lua的垃圾收集器只能回收那些它认为是垃圾的东西,不会回收用户认为是垃圾的东西。比如栈,栈由一个数组和一个顶部索引实现,如果弹出一个元素仅仅递减顶部索引,那么仍然停留在数组中的顶部
>Lua的垃圾收集器只能回收那些它认为是垃圾的东西,不会回收用户认为是垃圾的东西。比如栈,栈由一个数组和一个顶部索引实现,如果弹出一个元素仅仅递减顶部索引,那么仍然停留在数组中的顶部对象,对Lua来说就不是垃圾。又比如存储在全局变量中的对象,即使程序不会再用它们,对Lua来说也不是垃圾。在这两种情况下,用户必须对对象变量赋值nil(t[i] = nil),才能释放它们。

>有时候,简单地清楚引用肯能够还不够,需要程序和gc进行更多的协作。例如,当一个对象处于数组中时,即使当前其他地方没有使用它,只要数组仍引用着它,它就无法被回收。也就是说,我们不想用t[i] = nil,也可以回收除了t引用外没有引用的对象。

>弱引用table(weak table)就是这么一种机制,用户用它告诉Lua这个table的引用不应该阻碍一个对象的回收。如果一个对象的所有引用都来自弱引用table,那么gc就可以回收这个对象了,并可以以某种形式来删除这些弱引用本身。

>table中有key和value,这两者都可以包含任意类型的对象。有3种弱引用table:具有弱引用key的table、具有弱引用value的table、同时具有弱引用key和弱引用value的table。无论哪种类型的弱引用table,只要有一个key或value被回收,那么它对应的整个key-value对都会从table中删除。

>table的弱引用类型通过元表中的__mode字段决定的,__mode是一个字符串,如果包含'k',key是弱引用的,如果包含'v',value是弱引用的,如果同时包含'k'和'v',key和value都是弱引用的。
a = {}
setmetatable(a, { __mode = "k" })
key = {}
a[key] = 1
key = {}
a[key] = 2
collectgarbage() -- 强制进行垃圾回收
for k, v in pairs(a) do print(v) end --> 2
第二个key值把第一个key值覆盖了,导致第一个key值没有被引用,导致强制垃圾回收时,被收回了。
key = nil
collectgarbage()
for k, v in pairs(a) do print(v) end
  -->无输出,此时key变量也没有引用a原来的第二个key值,也导致被回收了。

>Lua只会回收弱引用table中的对象,像数字和布尔这样的“值”是不可回收的,字符串有些特殊,从实现的角度看,字符串是可以回收的,但从程序员的角度看,字符串就是值,而非对象,和数字和布尔一样,是不可回收的。

>备忘录(memoire)函数:
-- 用空间换时间,loadstring的时间成本很高,用一个辅助table记录下所有调用loadstring的结果。
local results = {}
function mem_loadstring (s)
local res = results[s]
if res == nil then --是否记录过
res = assert(loadstring(s))
results[s] = res -- 备以后用
end
return res
end
--改进:节省的时间非常客观,但results可能会把内存耗掉,弱引用table可以解决这个问题,让results具有弱引用的value即可。
local results = {}
setmetatable(results, { __mode = "v" })  -- 由于key是字符串,对弱引用table没有影响,所以完全可以用"kv"代替"v",不过有点画蛇添足了。
function mem_loadstring (s)
local res = results[s]
if res == nil then
res = assert(loadstring(s))
results[s] = res
end
return res
end
>“备忘录”技术还可以用来确保某类对象的唯一性。
function createRGB (r, g, b)
return { red = r, green = g, blue = b }
end

--改进:复用具有相同颜色的table,备忘录table的key根据颜色分量生成。
local results = {}
setmetatable(results, { __mode = "v" })
function createRGB (r, g, b)
local key = r .. "-" .. g .. "-" .. b
local color = results[key]
if color == nil then
color = { red = r, green = g, blue = b }
results[key] = color -- 备以后用
end
return color
end
>弱引用table还可以将对象与属性关联起来。当对象没有其他引用时,Lua可以回收时,弱引用table中对应的键值对也会删除。
--用弱引用table将每个table与其默认值关联起来(第13章“元表与元方法”有提)。
local defaults = {}
setmetatable(defaults, { __mode = "k" })
local mt = { __index = function (t) return defaults[t] end {
function setDefault (t, d)
defaults[t] = d
setmetatable(t, mt)
end
--重复的默认值复用同样的元表,不同的默认值使用不同的元表(第13章“元表与元方法”有提)。
local metas = {}
setmetatable(metas, { __mode = "v" })
function setDefaults (t, d)
local mt = metas[d]
if mt == nil then
mt = { __index = function () return d end}
metas[d] = mt -- 备以后用
end
setmetatable(t, mt)
end

第一种做法为每个table的默认值(defaults中的一个键值对)使用内存,第二种做法为每个不同的默认值(一个新table、一个新closure(if语句会产生closure???)和metas中的一个键值对)使用一组内存,如果程序有上千个table和一些默认值,采用第二种做法,如果只有很少的table或table的默认值很少相同的,采用第一种做法。

推荐阅读
  • 本文介绍了 JSON Schema 和 XML Schema 的基本概念,并详细讲解了如何使用 AJV 进行 JSON 数据校验。通过具体的示例和扩展方法,帮助读者更好地理解和应用这些工具。 ... [详细]
  • 本文探讨了 TypeScript 中泛型的重要性和应用场景,通过多个实例详细解析了泛型如何提升代码的复用性和类型安全性。 ... [详细]
  • PHP函数的工作原理与性能分析
    在编程语言中,函数是最基本的组成单元。本文将探讨PHP函数的特点、调用机制以及性能表现,并通过实际测试给出优化建议。 ... [详细]
  • Redis 是一个高性能的开源键值存储系统,支持多种数据结构。本文将详细介绍 Redis 中的六种底层数据结构及其在对象系统中的应用,包括字符串对象、列表对象、哈希对象、集合对象和有序集合对象。通过12张图解,帮助读者全面理解 Redis 的数据结构和对象系统。 ... [详细]
  • C#本随笔为个人复习巩固知识用,多从书上总结与python基础教程理解归纳得来,如有错误烦请指正面向对象的三大基本特征:封装、继承、多态 ... [详细]
  • Java 中的控制流与作用域
    本文详细介绍了 Java 中的控制流语句,包括块作用域、if 语句、for 循环、while 循环、do-while 循环、switch 语句以及 break 和 continue 语句的使用方法。通过具体的代码示例,帮助读者更好地理解和应用这些控制流结构。 ... [详细]
  • 在项目需要国际化处理时,即支持多种语言切换的功能,通常有两种方案:单个包和多个包。本文将重点讨论单个包的实现方法。 ... [详细]
  • java解析json转Map前段时间在做json报文处理的时候,写了一个针对不同格式json转map的处理工具方法,总结记录如下:1、单节点单层级、单节点多层级json转mapim ... [详细]
  • 深入解析Java中的空指针异常及其预防策略
    空指针异常(NullPointerException,简称NPE)是Java编程中最常见的异常之一。尽管其成因显而易见,但开发人员往往容易忽视或未能及时采取措施。本文将详细介绍如何有效避免空指针异常,帮助开发者提升代码质量。 ... [详细]
  • iOS snow animation
    CTSnowAnimationView.hCTMyCtripCreatedbyalexon1614.Copyright©2016年ctrip.Allrightsreserved.# ... [详细]
  • C语言编写线程池的简单实现方法
    2019独角兽企业重金招聘Python工程师标准好文章,一起分享——有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带 ... [详细]
  • PHP 5.5.31 和 PHP 5.6.17 安全更新发布
    PHP 5.5.31 和 PHP 5.6.17 已正式发布,主要包含多个安全修复。强烈建议所有用户尽快升级至最新版本以确保系统安全。 ... [详细]
  • 本文介绍了 Oracle SQL 中的集合运算、子查询、数据处理、表的创建与管理等内容。包括查询部门号为10和20的员工信息、使用集合运算、子查询的注意事项、数据插入与删除、表的创建与修改等。 ... [详细]
  • 开发笔记: URL参数处理与API请求示例
    本文记录了如何在开发过程中处理URL参数,并通过GET和POST方法发送API请求的具体步骤。 ... [详细]
  • 稀疏数组是一种用于存储和处理大部分元素为零或相同值的数组的技术。通过记录非零元素的位置和值,稀疏数组可以显著减少存储空间和提高处理效率。 ... [详细]
author-avatar
李2502933835
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有