简体   繁体   English

在Lua有什么像指针吗?

[英]Is there anything like pointers in Lua?

I'm new to Lua and I want to create a table [doh] which would store values like: 我是Lua的新手,我想创建一个表[doh],它可以存储以下值:

parent.child[1].value = "whaterver"
parent.child[2].value = "blah"

however, most often there's only one child, so it would be easier to access the value like this: 但是,大多数情况下,通常只有一个孩子,所以访问这个值会更容易:

parent.child.value

To make things simpler, I would like to store my values, in a way, that 为了使事情更简单,我想以某种方式存储我的价值观

parent.child[1].value == parent.child.value

But to do this I would have to store this value twice in the memory. 但要做到这一点,我必须将此值存储在内存中两次。 Is there any way I could do it, so that: 我有什么方法可以做到这一点,所以:

parent.child.value points to parent.child[1].value

without storing the value twice in the memory? 没有将值存储在内存中两次?

Additional question is, how to check how much memory does a table take? 另外一个问题是,如何检查表占用多少内存?

but the value will be stored as string, so it's a string that needs to be referenced in both places, not table. 但是该值将存储为字符串,因此它是一个需要在两个地方而不是表格中引用的字符串。

First, all types (except booleans, numbers and light userdata) are references - if t is a table and you do t2 = t , then both t and t2 are references to the same table in memory. 首先,所有类型(布尔值,数字和轻用户数据除外)都是引用 - 如果t是一个表而你做t2 = t ,那么tt2都是对内存中同一个表的引用。

Second thing - string are interned in Lua. 第二件事 - 字符串在Lua中实现。 That means that all equal strings, like "abc" and the result of "ab".."c" are actually a single string. 这意味着所有相等的字符串,如"abc""ab".."c"结果实际上是一个字符串。 Lua also stores only references to strings. Lua还只存储对字符串的引用。 So you should not worry about memory - there is only a single instance of the string at a time. 所以你不应该担心内存 - 一次只有一个字符串实例。

You can safely do parent.child.value = parent.child[1].value , you will only use a memory for one slot in a table (a few bytes), no string will be copied, only referenced. 你可以安全地做parent.child.value = parent.child[1].value ,你只会在一个表中使用一个内存(几个字节),不会复制任何字符串,只会被引用。

Lua tables (often used as objects) are not copied, but referenced. Lua表(通常用作对象)不会被复制,而是被引用。 (internally, a pointer is used to them) (在内部,指针用于它们)

This is a nice application for using metatables: 这是一个很好的使用metatables的应用程序:

parent={
    child={
        {value="whatever"},
        {value="blah"}
    }
}
setmetatable(parent.child,{__index=parent.child[1]})

If an index is not found in the child table (like 'value'), it gets looked up in the table that's the value of __index of the metatable (the first element of child in this case). 如果在子表中找不到索引(如'value'),则会在表中查找metatable的__index值(在本例中为child的第一个元素)。

Now there is a problem with the above code which we can see as folows: 现在上面的代码存在问题,我们可以看作如下:

print(parent.child.value) -- prints whatever
parent.child[1]=nil --remove first child
print(parent.child.value) -- still prints whatever!

This is because the metatable keeps a reference to the first child table, preventing it from being reaped. 这是因为metatable保留对第一个子表的引用,防止它被收获。 The workaround for this kind of stuff is A) making the metatable a weak table, or B) make the __index field a function, instead of referencing it to a table. 这种东西的解决方法是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.

If you're really interested to read up on metatables, try reading Programming in Lua, chapter 13 and chapter 17 (weak tables) . 如果您真的有兴趣阅读元数据,请尝试阅读Lua编程,第13 章和第17章(弱表) Lua-Users wiki on MetaMethods might also be interesting. MetaMethods上的Lua-Users wiki也可能很有趣。

With C arrays, parent.child and parent.child[0] are equivalent because of pointer arithmetic. 对于C数组, parent.childparent.child[0]因指针算法而等效。 You really shouldn't try to emulate one of the most error-prone, confusing and redundant features of C just because you like the style. 你真的不应该试图模仿C中最易出错,最令人困惑和冗余的功能之一,因为你喜欢这种风格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM