我是Lua的新手,我想创建一个表[doh],它会存储以下值:
parent.child[1].value = "whaterver"
parent.child[2].value = "blah"
然而,大多数情况下,通常只有一个孩子,因此更容易访问这样的值:
parent.child.value
为了简单起见,我希望以某种方式存储我的价值
parent.child[1].value == parent.child.value
但要做到这一点,我必须将此值存储在内存中两次。 有什么方法可以做到,所以:
parent.child.value points to parent.child[1].value
没有将值存储在内存中两次?
另外一个问题是,如何检查表占用多少内存?
答案 0 :(得分:9)
但该值将存储为字符串,因此它是一个需要的字符串 在两个地方都被引用,而不是表格。
首先,所有类型(布尔值,数字和灯光用户数据除外)都是引用 - 如果t
是一个表而您执行t2 = t
,那么t
和t2
是对内存中同一个表的引用。
第二件事 - 字符串在Lua中实现。这意味着所有相等的字符串,如"abc"
和"ab".."c"
的结果实际上是一个字符串。 Lua还只存储对字符串的引用。所以你不应该担心内存 - 一次只有一个字符串实例。
你可以放心地做parent.child.value = parent.child[1].value
,你只会在一个表中使用一个内存(几个字节),不会复制任何字符串,只能被引用。
答案 1 :(得分:3)
Lua表(通常用作对象)不会被复制,而是被引用。 (在内部,指针用于它们)
答案 2 :(得分:3)
这是一个很好的使用元表的应用程序:
parent={
child={
{value="whatever"},
{value="blah"}
}
}
setmetatable(parent.child,{__index=parent.child[1]})
如果在子表中找不到索引(比如'value'),它会在表格中查找,该表格是metatable的__index值(在这种情况下是子节点的第一个元素)。
现在上面的代码存在问题,我们可以看作如下:
print(parent.child.value) -- prints whatever
parent.child[1]=nil --remove first child
print(parent.child.value) -- still prints whatever!
这是因为metatable保留对第一个子表的引用,防止它被收集。这种东西的解决方法是A)使metatable成为弱表,或者B)使__index字段成为一个函数,而不是将它引用到表中。
-- A)
setmetatable(parent.child, setmetatable(
{__index=parent.child[1]} -- metatable for the child table
{__mode='v'}-- metatable for the metatable, making it have weak keys
)
)
parent.child[1]=nil
print(parent.child.value) --returns nil
parent.child[1]={value='foo'}
print(parent.child.value) -- prints nil, the metatable references to a non-existant table.
-- hence solution B)
setmetatable(parent.child, {__index=function(t,k) return parent.child[1][k]})
print(parent.child.value) -- 'whatever'
parent.child[1]=nil
print(parent.child.value) -- nil
parent.child[1]={value='foobar'
print(parent.child.value) -- foobar, now it will always refer to the table at child[1], even when it changes.
如果您真的有兴趣阅读元数据,请尝试阅读Programming in Lua, chapter 13和chapter 17 (weak tables)。 Lua-Users wiki on MetaMethods也可能很有趣。
答案 3 :(得分:0)
对于C数组,由于指针算法,parent.child
和parent.child[0]
是等价的。你真的不应该试图模仿C中最易出错,最令人困惑和冗余的功能之一,因为你喜欢这种风格。