Lua弱引用

11

我知道Lua中弱表的功能,但我希望有一个只包含单个变量的弱引用。

我看过这个提案,其中建议的API如下:

-- creation
ref = weakref(obj)
-- dereference
obj = ref()

看起来这很理想。但是在其他文档中似乎找不到这个信息,只有弱引用表。

是否有类似于Python的 对对象的弱引用 功能?


1
你最终想要做什么?如果你真的需要,你可以使用带有元表的表来模拟这个过程(或者使用newproxy和元表)。 - Etan Reisner
我正在使用middleclass进行面向对象编程,将一个闭包从objA传递到objB。当objA超出范围时,闭包会阻止两个实例被GC回收,因为它包含对objA的引用。以前从未听说过newproxy,打算去Google一下... - MarkNS
1
是的,你不需要它来实现这个想法,只需使用userdata代替表格即可。这个想法是创建一个带有元表的表格,支持__call以获取ref()语法,其中表格本身或元表都是弱引用并保存了引用。 - Etan Reisner
你不需要元表来实现弱引用的想法。没有它,你只需要使用ref.realref.obj或其他类似的东西代替ref() - Etan Reisner
“这个提案”是一份来自2004年的文件,在那时你不能(我猜)直接在Lua中创建弱表(即不使用C API)。但现在情况已经不同了。你已经得到了两个很好的答案,告诉你如何做到这一点。 - Niccolo M.
显示剩余2条评论
2个回答

10
当Lua不能提供某些功能时,通常可以从其他基本元素中实现它。
function weakref(data)
    local weak = setmetatable({content=data}, {__mode="v"})
    return function() return weak.content end
end

我们创建了一个只包含数据的弱表。然后我们返回一个函数,当调用该函数时,返回该表的内容。
(注意,弱引用可能要等到垃圾回收才能被释放,而字面量永远不会被垃圾回收。)

很遗憾这个答案没有被采纳 - 它比被采纳的那个更好,而且提前了一分钟。 - fluffy
1
另一个答案有一些非常重要的优点...具体来说,它有潜力创建更少的垃圾,因为我的解决方案为每个调用创建一个对象和该对象上的闭包,而被接受的解决方案仅创建表格。(两者都会不必要地每次创建新的元表,但这可以被提取出来并重复使用)。 - kazagistar
啊,好的观点。大多数情况下,我只需要了解__mode="v" - 在我的用例中,我正在创建一个图像池,并且只想要一个弱表,其中表中的所有值都是可收集的。 - fluffy

5
我相信这样做可以满足你的需求:

类似于这样的代码可以实现你想要的功能:

local obj = {value = "obj.value"}

local ref = setmetatable({real = obj}, {__mode = "v", __call = function(self) return self.real end})

print(obj.value)
print(ref.real.value)
print(ref().value)

obj = nil
collectgarbage()
collectgarbage()

print(obj)
print(ref.real)
print(ref())
< p > __call 部分是可选的,但它为您提供了ref()调用语法。 如果没有它,您必须使用直接访问版本。 < /p >

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接