gpt4 book ai didi

memory - 在 Lua 中通过引用删除变量

转载 作者:行者123 更新时间:2023-12-01 12:39:43 24 4
gpt4 key购买 nike

我在几个表中得到了几个对象。
多个功能更改对象并将其移交给其他功能。

假设我的表是这样的:

objectTable = {obj1, obj2, obj3}
otherobjTable = {objA, objB, objC, objD}

假设这些是在 main.lua 中初始化的。

现在,当跟踪 obj1 时,它被一个函数改变,该函数改变它并提供对另一个函数的引用,另一个函数又改变它。
一个步骤可能如下所示:
function()
if something then func(obj_1)
elseif something else then func(obj_2)
elseif something other then func(obj_3)
//... and so on...
end

function func(received_Object)
if something then
table.insert(received_Object, a value)
end
callAnotherFunction(received_Object)
end

function callAnotherFunction(received_Object)
if input == "Delete it" then
local name = received_Object.name
received_Object = nil
return string.format("%s was deleten", name)
else
return false
end
end

现在的问题是,在 received_Object = nil 之后,引用指向 nil 但对象仍然存在。我怎样才能确定删除它?

最佳答案

在 Lua 中,某些类型(如表)总是通过引用传递,而其他类型(如数字)总是通过值传递。

此外,Lua 是一种内存由垃圾收集器管理的语言。当没有更多的引用(我们称之为 anchor )时,垃圾收集器会删除一个对象(例如一个表)。

现在这个代码:

local t = {}
local t1 = {t}
someFunc(t)

为该表创建三个 anchor 。当 someFunc 将另一个该表作为参数传递给另一个函数时,将创建第四个 anchor (以该函数的局部变量/参数的形式)。

为了让垃圾收集器清除第一个表,所有这些引用都必须消失(通过分配 nil 或超出范围)。

重要的是要了解,当您将 nil 分配给本地 t 时,并不意味着该表将被删除。更不用说对该表的所有引用都将无效。这意味着你只是释放了这个 anchor ,在这一点上它只是四个 anchor 之一。

可能的解决方案

一种可能的解决方案是传递包含对象的表以及存储对象的索引/键:
function func(myTable, myKey)
...
end

现在,如果在这个函数中你这样做:
myTable[myKey] = nil

(并且没有其他 anchor 被创建),键下的对象将不再有指向它的引用,并将被标记为下一轮垃圾收集器清除。当然, callAnotherFunction 也必须以同样的方式修改:
callAnotherFunction(myTable, myKey)
...
end

如果您在这些函数中对该对象执行许多操作,您可以将其缓存到一个局部变量中以避免多次表查找。这是可以的,因为当函数完成时, anchor 将与局部变量一起被清除:
callAnotherFunction(myTable, myKey)
local myObj = myTable[myKey]
...
if myCondition then myTable[myKey] = nil end
end --here myObj is no longer valid, so the anchor is gone.

另一种解决方案

由于您无法像上面建议的那样更改代码,因此您可以实现以下逻辑:

为包含对象的表创建元表:
local mt = {
__newindex = function(tab, key, val)
--if necessary and possible, perform a check, if the value is in fact object of your type
val.storeTableReference(tab, key) --you'll have to implement this in your objects
rawset(tab, key, val);
end
}

local container1 = setmetatable({}, mt)
local container2 = setmetatable({}, mt)

现在,当您将对象插入该表时:
container1.obj1 = obj1
container2.obj1 = obj1

每次 __newindex 元方法都会使用适当的引用调用 obj1.storeTableReference。此函数将这些引用存储在(例如)内部表中。

唯一需要实现的是释放这些引用的对象方法:
myObj:freeReferences = function()
for k, v in ipairs(self:tableReferences) do --assuming that's where you store the references
k[v] = nil
end
tableReferences = {} --optional, replaces your reference table with an empty one
end

现在这个解决方案有点笨拙,因为您需要注意以下几点:
  • __newindex 只有在第一次创建 key 时才会被触发。所以container1.obj = obj1container1.obj = obj2 只会
    在第一次分配时触发 __newindex。解决办法是
    首先将 obj 键设置为 nil ,然后设置为 obj2
  • 当您在该表中手动将 obj 设置为 nil(或设置为另一个
    对象),您需要确保对象存储的引用
    也会被清除。
  • 关于memory - 在 Lua 中通过引用删除变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26138546/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com