Lua弱引用

我正在使用 Lua 开发一个项目,其中我将创建表并将它们存储在主表中以便在以后删除。我将把对这些表的引用传递给其他兄弟表。

master = {}
table.insert(master, {name = 'hello'})
table.insert(master, {name = 'world', pre = master[1]})

问题在于,当我想要从主表中删除引用时,引用仍然存在于 master[2] 中。显然,我的第一个解决方案是使表具有弱值。 ( 通过元表上的 .__mode,未在此处显示)

这起作用,只要我不会在这些表中存储单一引用的表,它就会起作用。

table.insert(master, {name = 'goodbye', pre = master[2], some_table = {123}})

第三个元素 some_table 最终会被收集,因为表具有弱值,并且此表 (some_table) 在其他任何地方都没有被引用。这是不期望的行为。我的最新解决方案涉及在主表中创建“弱引用对象”来引用表。以下是一个天真的实现:

function WeakRef(t)
    r = {__mode = 'v', __index = t, __newindex = t}
    setmetatable(r, r)
    return r
end

这些弱引用对象类似于 boost::weak_ptr,并实现了我的目标,但我不确定它们是否是我问题的最佳解决方案。

是否有更好的方法; 更优雅的解决方案? 我的设计,需要这个主表,也许有缺陷?

原文链接 https://stackoverflow.com/questions/7451734

点赞
stackoverflow用户312586
stackoverflow用户312586

假设:

  1. 您希望主控制器成为“定义对象是否存在的唯一位置”
  2. 您的对象之间可以具有链接关系

那么最简单的架构可能是保留每个对象的一个成员作为“中间代理”,负责管理对其他对象的引用。以下是步骤:

  1. master 设为常规表格(不是弱表)
  2. 在每个物理对象上,创建一个名为 links(或适合您逻辑的其他名称)的弱表
  3. 将所有 links 表设为弱表。使用它们来存储对其他对象的引用。

这是一个可能的实现。我在 Lua 5.1 中尝试了它:

local function newWeakTable()
  return setmetatable({}, {__mode = "v"})
end

local master = {}

-- 创建两个物理对象
local obj1 = { name = "obj1", links = newWeakTable() }
local obj2 = { name = "obj2", links = newWeakTable() }

-- 将它们连接起来
obj2.links.pre = obj1

-- 将它们插入主控制器中
table.insert(master, obj1)
table.insert(master, obj2)

-- 主控制器有两个对象,并且它们被连接起来了
assert(#master == 2)
assert(obj2.links.pre == obj1)

-- 将 obj1 从主控制器中移除,并移除变量引用
table.remove(master, 1)
obj1 = nil

-- 手动运行垃圾回收
collectgarbage("collect")

-- 现在主控制器只有一个对象,链接已消失
assert(#master == 1)
assert(obj2.links.pre == nil)

print("一切都如预期的那样")
2011-09-17 01:43:12