1

我正在使用 lua C api 来运行与本机类接口的脚本。我正在利用 Qt 的 MOC 获取运行时类型信息。到目前为止,我已经实现了我希望 lua 能够与之对话的所有类的创建、删除和索引。

这是我现在可以做的示例脚本:

myObject = MyClass.new()  --creates new userdata
otherObject = OtherClass.new()  --creates new userdata

myObject:functionForOthers(otherObject)  --method that takes userdata as argument

在该脚本中,otherObject被创建并保留在堆栈中。然后将其传递给functionForOthers()接受OtherClass对象作为参数的对象。

但是,如果我不想otherObject被放入堆栈怎么办?如果我希望它是一个只存在于函数调用范围内的匿名变量怎么办?

myObject = MyClass.new()

myObject:functionForOthers(OtherClass.new())

这仍然有效,但是OtherObject实例被创建但从未分配给变量,使其在堆栈中无法访问,直到范围结束。这不会导致任何直接的问题,但它会困扰我的内存效率部分。

我有很多本地代码处理这些操作的后端,但它的基本要点是它new是一个全局表字段,MyClassOtherClass指向一个本地 CreateObject 函数。从那里,在调用后创建类的实例并将其存储在用户数据中lua_newuserdata()

functionForOthers()调用使用__index指向本机 IndexObject 函数的元方法,该方法如果存在则调用该方法。

实现匿名用户数据变量的基本方法是什么?我仍然希望这两个脚本都是有效的方法,我只想要一种将第二个脚本的OtherClass对象保持在范围内的方法,直到函数调用完成。

4

1 回答 1

1

感觉就像您误解了 Lua 的某些部分。

将某个对象作为参数传递给函数并不会将该对象“留在”堆栈上。堆栈只存储对对象的引用。对同一对象的另一个引用存储在otherObject变量中。当您将变量作为参数传递给您时,functionForOthers()您会将该引用按值复制到堆栈中,并且一旦被调用的函数返回控制权,该引用就会从堆栈中弹出。

对象本身存储在 Lua 堆上。当垃圾收集器发现没有对该对象的引用时,它最终会被销毁/收集。对象在作用域结束时不会被销毁,只会丢失引用。何时实际删除对象取决于垃圾收集器。

如果您担心内存,可以collectgarbage()定期调用。不过,这可能会使您的程序卡顿一段时间,因此请选择合适的时机。否则你可以完全忽略它,只要确保你没有在一些长期存在的结构(全局变量、注册表或你自己的字典/缓存)中收集对对象的引用。堆栈上的引用很快就会被删除,除非您无意中创建了非常深或无限的递归调用。无法到达的对象将被自动删除,这就是标记和清除垃圾收集器的工作方式。

于 2018-10-22T07:49:24.110 回答