【问题标题】:Is there anything like pointers in Lua?Lua中有类似指针的东西吗?
【发布时间】:2014-01-11 17:53:47
【问题描述】:

我是 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

不在内存中存储两次值?

另外一个问题是,如何查看一张表占用了多少内存?

【问题讨论】:

    标签: pointers lua


    【解决方案1】:

    但该值将存储为字符串,所以它是一个字符串,需要 在两个地方都被引用,而不是表格。

    首先,所有类型(布尔值、数字和轻量级用户数据除外)都是引用 - 如果t 是一个表,而您使用t2 = t,那么tt2 都是对内存中同一个表的引用.

    第二件事 - 字符串在 Lua 中被实习。这意味着所有相等的字符串,如"abc""ab".."c" 的结果实际上是一个字符串。 Lua 也只存储对字符串的引用。所以你不应该担心内存 - 一次只有一个字符串实例。

    您可以放心地使用parent.child.value = parent.child[1].value,您只会将内存用于表中的一个插槽(几个字节),不会复制字符串,仅引用。

    【讨论】:

    • 感谢您对我 7 年的旧答案的非常有见地的评论。我相信它扩展了每个人对 Lua 引用类型的了解。
    【解决方案2】:

    Lua 表(通常用作对象)不会被复制,而是被引用。 (在内部,一个指针用于它们)

    【讨论】:

    • 但该值将存储为字符串,因此它是一个需要在两个地方引用的字符串,而不是表。你的答案在这种情况下也有效吗?
    • 现在正确的问题是如何检查表的内存大小?这样我们就可以肯定地回答这个问题了。
    【解决方案3】:

    这是一个很好的使用元表的应用程序:

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

    如果在子表中未找到索引(如“值”),则会在表中查找元表的 __index 值(在本例中为子表的第一个元素)。

    现在上面的代码有一个问题,我们可以看到如下:

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

    这是因为元表保留了对第一个子表的引用,防止它被收割。这类东西的解决方法是 A) 使元表成为弱表,或 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 13chapter 17 (weak tables)Lua-Users wiki on MetaMethods 也可能很有趣。

    【讨论】:

    • 非常感谢,它看起来很有趣。我仍在为 setmetatable 和在 lua 中使用表作为对象而苦苦挣扎,但我会试一试。我将要使用的这个结构是只读的,不会进行任何修改,所以它实际上可以正常工作。非常酷,非常感谢!
    【解决方案4】:

    对于 C 数组,parent.childparent.child[0] 由于指针运算而等效。你真的不应该仅仅因为你喜欢这种风格就试图模仿 C 语言中最容易出错、最混乱和冗余的特性之一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-10
      • 1970-01-01
      • 2021-08-04
      • 2012-05-31
      • 2012-11-27
      • 2017-11-21
      • 2012-08-03
      相关资源
      最近更新 更多