2011-12-08 76 views
5

我是新來的Lua,我想創建一個表[DOH]這將存儲像值:Lua裏有什麼像指針嗎?

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 

,而不在內存的兩倍存儲的價值?

另外的問題是,如何檢查一張表佔用多少內存?

回答

10

但該值將存儲爲字符串,因此它需要 在這兩個地方,而不是表中引用的字符串。

首先,所有類型(除布爾值,數字和光用戶數據)的引用 - 如果t是一個表,你做t2 = t,那麼這兩個tt2是在內存中相同的表引用。

第二件事 - 字符串在Lua中實現。這意味着所有相同的字符串,如​​和"ab".."c"的結果實際上是單個字符串。 Lua也只存儲對字符串的引用。所以你不應該擔心內存 - 一次只有一個字符串實例。

你可以安全地做parent.child.value = parent.child[1].value,你只會在一個表中使用一個存儲空間(幾個字節),沒有字符串會被複制,只能被引用。

+0

真棒,非常感謝。 – Krystian

3

Lua表(通常用作對象)不會被複制,而是被引用。 (內部,一個指針用於它們)

+0

但該值將被存儲爲字符串,所以它是一個字符串,需要在兩個地方引用,而不是表。這種情況下你的答案是否有效? – Krystian

+0

我認爲是的。 –

+0

現在正確的問題是如何檢查表的內存大小?這樣我們就可以肯定地回答這個問題。 – Krystian

3

這是使用元表一個不錯的應用程序:

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

如果在子表中沒有找到一個索引(如「價值」),它就會在那的__index的值表中查找metatable(在這種情況下是孩子的第一個元素)。

現在有與上面的代碼有問題,我們可以看到作爲folows:

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

這是因爲元表保持到第一子表的引用,防止它被收割。這種東西的解決方法是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 13chapter 17 (weak tables)Lua-Users wiki on MetaMethods也可能很有趣。

+0

非常感謝這看起來很有趣。我仍然在使用setmetatable和使用表格作爲lua中的對象,但我會給它一個鏡頭。我將要使用的這種結構將被用於只讀,並且不會進行修改,所以它可能實際上工作正常。非常酷,非常感謝! – Krystian

0

使用C數組,parent.childparent.child[0]是等價的,因爲指針算術。你真的不應該嘗試模仿C中最容易出錯,混亂和冗餘的特性之一,因爲你喜歡這種風格。